@graphrefly/graphrefly 0.47.2 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/dist/base/composition/index.cjs +4 -3
  2. package/dist/base/composition/index.cjs.map +1 -1
  3. package/dist/base/composition/index.d.cts +14 -5
  4. package/dist/base/composition/index.d.ts +14 -5
  5. package/dist/base/composition/index.js +8 -8
  6. package/dist/base/index.cjs +152 -78
  7. package/dist/base/index.cjs.map +1 -1
  8. package/dist/base/index.d.cts +2 -2
  9. package/dist/base/index.d.ts +2 -2
  10. package/dist/base/index.js +75 -70
  11. package/dist/base/io/index.cjs +31 -17
  12. package/dist/base/io/index.cjs.map +1 -1
  13. package/dist/base/io/index.d.cts +32 -5
  14. package/dist/base/io/index.d.ts +32 -5
  15. package/dist/base/io/index.js +1 -1
  16. package/dist/base/mutation/index.cjs +21 -0
  17. package/dist/base/mutation/index.cjs.map +1 -1
  18. package/dist/base/mutation/index.d.cts +23 -1
  19. package/dist/base/mutation/index.d.ts +23 -1
  20. package/dist/base/mutation/index.js +3 -1
  21. package/dist/base/sources/browser/index.cjs +5 -3
  22. package/dist/base/sources/browser/index.cjs.map +1 -1
  23. package/dist/base/sources/browser/index.d.cts +20 -2
  24. package/dist/base/sources/browser/index.d.ts +20 -2
  25. package/dist/base/sources/browser/index.js +5 -3
  26. package/dist/base/sources/browser/index.js.map +1 -1
  27. package/dist/base/sources/event/index.cjs +28 -0
  28. package/dist/base/sources/event/index.cjs.map +1 -1
  29. package/dist/base/sources/event/index.d.cts +67 -3
  30. package/dist/base/sources/event/index.d.ts +67 -3
  31. package/dist/base/sources/event/index.js +4 -1
  32. package/dist/base/sources/index.cjs +75 -37
  33. package/dist/base/sources/index.cjs.map +1 -1
  34. package/dist/base/sources/index.d.cts +1 -1
  35. package/dist/base/sources/index.d.ts +1 -1
  36. package/dist/base/sources/index.js +5 -2
  37. package/dist/{chunk-R6ZCSXKX.js → chunk-23MAWVOJ.js} +3 -3
  38. package/dist/{chunk-MS3WPRJR.js → chunk-3REMCHSS.js} +6 -6
  39. package/dist/chunk-3REMCHSS.js.map +1 -0
  40. package/dist/{chunk-CEVNQ74M.js → chunk-3YGXPUHW.js} +2 -2
  41. package/dist/{chunk-CEVNQ74M.js.map → chunk-3YGXPUHW.js.map} +1 -1
  42. package/dist/{chunk-6ZLCPUXS.js → chunk-46X2EFQH.js} +15 -4
  43. package/dist/chunk-46X2EFQH.js.map +1 -0
  44. package/dist/{chunk-NY2PYHNC.js → chunk-5UY3PNFY.js} +12 -5
  45. package/dist/chunk-5UY3PNFY.js.map +1 -0
  46. package/dist/{chunk-FQSQONOU.js → chunk-65OM4XLQ.js} +49 -3
  47. package/dist/chunk-65OM4XLQ.js.map +1 -0
  48. package/dist/{chunk-3PSLNJDU.js → chunk-6DQYBIHW.js} +314 -49
  49. package/dist/chunk-6DQYBIHW.js.map +1 -0
  50. package/dist/{chunk-LDCSZ72P.js → chunk-6YBER5UP.js} +3 -3
  51. package/dist/{chunk-LDCSZ72P.js.map → chunk-6YBER5UP.js.map} +1 -1
  52. package/dist/{chunk-3O3NKZJW.js → chunk-7T7WLEPM.js} +24 -3
  53. package/dist/chunk-7T7WLEPM.js.map +1 -0
  54. package/dist/{chunk-PKPO3JTZ.js → chunk-AQAKDE7F.js} +29 -11
  55. package/dist/chunk-AQAKDE7F.js.map +1 -0
  56. package/dist/{chunk-6MRSX3YK.js → chunk-B5Y5GPD5.js} +2 -2
  57. package/dist/{chunk-BXGZFGZ4.js → chunk-C5QD5DQX.js} +22 -1
  58. package/dist/chunk-C5QD5DQX.js.map +1 -0
  59. package/dist/{chunk-4XCHZRUJ.js → chunk-D5YGR4TP.js} +58 -7
  60. package/dist/chunk-D5YGR4TP.js.map +1 -0
  61. package/dist/{chunk-NPRP3MCV.js → chunk-DHDCOOJU.js} +2 -2
  62. package/dist/chunk-DHDCOOJU.js.map +1 -0
  63. package/dist/{chunk-VP3TIUDF.js → chunk-DVTDF5OI.js} +2 -2
  64. package/dist/{chunk-OXD5LFQP.js → chunk-G7H6PN7P.js} +2 -2
  65. package/dist/{chunk-EL5VHUGK.js → chunk-GGKHHG5Y.js} +32 -18
  66. package/dist/chunk-GGKHHG5Y.js.map +1 -0
  67. package/dist/{chunk-446I4EGD.js → chunk-J5TBZFBD.js} +2 -2
  68. package/dist/{chunk-7AVQIGF6.js → chunk-K4ZYJ4EM.js} +554 -460
  69. package/dist/chunk-K4ZYJ4EM.js.map +1 -0
  70. package/dist/{chunk-QFE5BQH7.js → chunk-LTSI7ULC.js} +2 -2
  71. package/dist/{chunk-5GVURVIG.js → chunk-MMHGYX44.js} +12 -2
  72. package/dist/{chunk-5GVURVIG.js.map → chunk-MMHGYX44.js.map} +1 -1
  73. package/dist/{chunk-KRFGO5QH.js → chunk-MQMTRKY3.js} +118 -43
  74. package/dist/chunk-MQMTRKY3.js.map +1 -0
  75. package/dist/{chunk-42FQ27MQ.js → chunk-MTODGQBR.js} +44 -179
  76. package/dist/chunk-MTODGQBR.js.map +1 -0
  77. package/dist/{chunk-FVINAAKA.js → chunk-NBK6QQMG.js} +14 -13
  78. package/dist/{chunk-FVINAAKA.js.map → chunk-NBK6QQMG.js.map} +1 -1
  79. package/dist/{chunk-KNU73RZW.js → chunk-NSA5K5G2.js} +2 -2
  80. package/dist/{chunk-MLTPJMH6.js → chunk-QQYULEZL.js} +2 -2
  81. package/dist/chunk-QSW4DFKE.js +31 -0
  82. package/dist/chunk-QSW4DFKE.js.map +1 -0
  83. package/dist/{chunk-VAZXUK6G.js → chunk-SUNCHMML.js} +2 -2
  84. package/dist/{chunk-EP4WVQLX.js → chunk-T2U6N3FV.js} +6 -6
  85. package/dist/{chunk-T7SP3EYR.js → chunk-T5URUIIY.js} +33 -24
  86. package/dist/chunk-T5URUIIY.js.map +1 -0
  87. package/dist/{chunk-VNXAF2KE.js → chunk-TPTZZV25.js} +6 -6
  88. package/dist/chunk-TPTZZV25.js.map +1 -0
  89. package/dist/{chunk-IOJDYUA7.js → chunk-V46JWFGV.js} +6 -5
  90. package/dist/chunk-V46JWFGV.js.map +1 -0
  91. package/dist/{chunk-WGDEBIP4.js → chunk-X6ESZDR6.js} +5 -6
  92. package/dist/chunk-X6ESZDR6.js.map +1 -0
  93. package/dist/{chunk-N65E26UL.js → chunk-XEWV254I.js} +2 -2
  94. package/dist/{chunk-N65E26UL.js.map → chunk-XEWV254I.js.map} +1 -1
  95. package/dist/{chunk-PTWADEH3.js → chunk-YBJVKMTM.js} +34 -14
  96. package/dist/chunk-YBJVKMTM.js.map +1 -0
  97. package/dist/{chunk-DDTS7F5O.js → chunk-ZW32BPXV.js} +12 -3
  98. package/dist/chunk-ZW32BPXV.js.map +1 -0
  99. package/dist/compat/index.cjs +51 -4
  100. package/dist/compat/index.cjs.map +1 -1
  101. package/dist/compat/index.d.cts +1 -1
  102. package/dist/compat/index.d.ts +1 -1
  103. package/dist/compat/index.js +6 -6
  104. package/dist/compat/nestjs/index.cjs +51 -4
  105. package/dist/compat/nestjs/index.cjs.map +1 -1
  106. package/dist/compat/nestjs/index.d.cts +1 -1
  107. package/dist/compat/nestjs/index.d.ts +1 -1
  108. package/dist/compat/nestjs/index.js +3 -3
  109. package/dist/{fallback-Bx46zqky.d.cts → fallback-BROR6ZhO.d.cts} +1 -1
  110. package/dist/{fallback-pIWW8A2d.d.ts → fallback-DO80aM_3.d.ts} +1 -1
  111. package/dist/{index-B_p8tnvf.d.cts → index-D1z3XcF9.d.cts} +1 -0
  112. package/dist/{index-_HDSmPyp.d.ts → index-DZ6yua0Q.d.ts} +1 -0
  113. package/dist/index.cjs +2215 -1676
  114. package/dist/index.cjs.map +1 -1
  115. package/dist/index.d.cts +10 -10
  116. package/dist/index.d.ts +10 -10
  117. package/dist/index.js +169 -146
  118. package/dist/index.js.map +1 -1
  119. package/dist/presets/ai/index.cjs +46 -0
  120. package/dist/presets/ai/index.cjs.map +1 -1
  121. package/dist/presets/ai/index.js +12 -12
  122. package/dist/presets/harness/index.cjs +130 -18
  123. package/dist/presets/harness/index.cjs.map +1 -1
  124. package/dist/presets/harness/index.d.cts +15 -5
  125. package/dist/presets/harness/index.d.ts +15 -5
  126. package/dist/presets/harness/index.js +22 -22
  127. package/dist/presets/index.cjs +222 -53
  128. package/dist/presets/index.cjs.map +1 -1
  129. package/dist/presets/index.d.cts +2 -2
  130. package/dist/presets/index.d.ts +2 -2
  131. package/dist/presets/index.js +45 -45
  132. package/dist/presets/inspect/index.cjs +63 -14
  133. package/dist/presets/inspect/index.cjs.map +1 -1
  134. package/dist/presets/inspect/index.d.cts +1 -1
  135. package/dist/presets/inspect/index.d.ts +1 -1
  136. package/dist/presets/inspect/index.js +6 -6
  137. package/dist/presets/resilience/index.cjs +29 -21
  138. package/dist/presets/resilience/index.cjs.map +1 -1
  139. package/dist/presets/resilience/index.d.cts +12 -8
  140. package/dist/presets/resilience/index.d.ts +12 -8
  141. package/dist/presets/resilience/index.js +3 -3
  142. package/dist/{rate-limiter-DpVbSYdH.d.cts → rate-limiter-DC26FM8J.d.cts} +10 -1
  143. package/dist/{rate-limiter-CEALq4N1.d.ts → rate-limiter-DyWpwpQP.d.ts} +10 -1
  144. package/dist/{reactive-layout-fswlBUvX.d.ts → reactive-layout-BBBWH0V_.d.cts} +85 -4
  145. package/dist/{reactive-layout-fswlBUvX.d.cts → reactive-layout-BBBWH0V_.d.ts} +85 -4
  146. package/dist/solutions/index.cjs +168 -47
  147. package/dist/solutions/index.cjs.map +1 -1
  148. package/dist/solutions/index.d.cts +2 -2
  149. package/dist/solutions/index.d.ts +2 -2
  150. package/dist/solutions/index.js +28 -28
  151. package/dist/{spawnable-5mDY501F.d.cts → spawnable-B2IlW60f.d.cts} +23 -2
  152. package/dist/{spawnable-D3lR0oQu.d.ts → spawnable-tttFz2Nh.d.ts} +23 -2
  153. package/dist/testing/index.cjs +94 -0
  154. package/dist/testing/index.cjs.map +1 -0
  155. package/dist/testing/index.d.cts +59 -0
  156. package/dist/testing/index.d.ts +59 -0
  157. package/dist/testing/index.js +73 -0
  158. package/dist/testing/index.js.map +1 -0
  159. package/dist/utils/ai/browser.cjs.map +1 -1
  160. package/dist/utils/ai/browser.d.cts +2 -2
  161. package/dist/utils/ai/browser.d.ts +2 -2
  162. package/dist/utils/ai/browser.js +6 -6
  163. package/dist/utils/ai/browser.js.map +1 -1
  164. package/dist/utils/ai/index.cjs +250 -166
  165. package/dist/utils/ai/index.cjs.map +1 -1
  166. package/dist/utils/ai/index.d.cts +108 -12
  167. package/dist/utils/ai/index.d.ts +108 -12
  168. package/dist/utils/ai/index.js +21 -19
  169. package/dist/utils/ai/node.cjs.map +1 -1
  170. package/dist/utils/ai/node.d.cts +5 -5
  171. package/dist/utils/ai/node.d.ts +5 -5
  172. package/dist/utils/ai/node.js +2 -2
  173. package/dist/utils/ai/node.js.map +1 -1
  174. package/dist/utils/cqrs/index.cjs +29 -3
  175. package/dist/utils/cqrs/index.cjs.map +1 -1
  176. package/dist/utils/cqrs/index.d.cts +12 -7
  177. package/dist/utils/cqrs/index.d.ts +12 -7
  178. package/dist/utils/cqrs/index.js +2 -2
  179. package/dist/utils/demo-shell/index.cjs +45 -19
  180. package/dist/utils/demo-shell/index.cjs.map +1 -1
  181. package/dist/utils/demo-shell/index.d.cts +1 -1
  182. package/dist/utils/demo-shell/index.d.ts +1 -1
  183. package/dist/utils/demo-shell/index.js +2 -2
  184. package/dist/utils/domain-templates/index.cjs.map +1 -1
  185. package/dist/utils/domain-templates/index.js +3 -3
  186. package/dist/utils/graphspec/index.cjs.map +1 -1
  187. package/dist/utils/graphspec/index.js +3 -3
  188. package/dist/utils/index.cjs +1642 -1225
  189. package/dist/utils/index.cjs.map +1 -1
  190. package/dist/utils/index.d.cts +7 -7
  191. package/dist/utils/index.d.ts +7 -7
  192. package/dist/utils/index.js +72 -54
  193. package/dist/utils/inspect/index.cjs +52 -4
  194. package/dist/utils/inspect/index.cjs.map +1 -1
  195. package/dist/utils/inspect/index.d.cts +32 -3
  196. package/dist/utils/inspect/index.d.ts +32 -3
  197. package/dist/utils/inspect/index.js +4 -4
  198. package/dist/utils/job-queue/index.cjs +46 -9
  199. package/dist/utils/job-queue/index.cjs.map +1 -1
  200. package/dist/utils/job-queue/index.d.cts +33 -3
  201. package/dist/utils/job-queue/index.d.ts +33 -3
  202. package/dist/utils/job-queue/index.js +2 -2
  203. package/dist/utils/memory/index.cjs +556 -462
  204. package/dist/utils/memory/index.cjs.map +1 -1
  205. package/dist/utils/memory/index.d.cts +203 -24
  206. package/dist/utils/memory/index.d.ts +203 -24
  207. package/dist/utils/memory/index.js +10 -2
  208. package/dist/utils/messaging/index.cjs.map +1 -1
  209. package/dist/utils/messaging/index.d.cts +4 -3
  210. package/dist/utils/messaging/index.d.ts +4 -3
  211. package/dist/utils/messaging/index.js +2 -2
  212. package/dist/utils/orchestration/index.cjs +9 -0
  213. package/dist/utils/orchestration/index.cjs.map +1 -1
  214. package/dist/utils/orchestration/index.js +3 -3
  215. package/dist/utils/process/index.cjs +32 -2
  216. package/dist/utils/process/index.cjs.map +1 -1
  217. package/dist/utils/process/index.d.cts +4 -3
  218. package/dist/utils/process/index.d.ts +4 -3
  219. package/dist/utils/process/index.js +2 -2
  220. package/dist/utils/reactive-layout/index.cjs +184 -55
  221. package/dist/utils/reactive-layout/index.cjs.map +1 -1
  222. package/dist/utils/reactive-layout/index.d.cts +128 -3
  223. package/dist/utils/reactive-layout/index.d.ts +128 -3
  224. package/dist/utils/reactive-layout/index.js +16 -8
  225. package/dist/utils/reduction/index.cjs.map +1 -1
  226. package/dist/utils/reduction/index.js +2 -2
  227. package/dist/utils/resilience/index.cjs +29 -20
  228. package/dist/utils/resilience/index.cjs.map +1 -1
  229. package/dist/utils/resilience/index.d.cts +1 -1
  230. package/dist/utils/resilience/index.d.ts +1 -1
  231. package/dist/utils/resilience/index.js +2 -2
  232. package/dist/utils/surface/index.cjs.map +1 -1
  233. package/dist/utils/surface/index.js +4 -4
  234. package/package.json +15 -3
  235. package/dist/chunk-3O3NKZJW.js.map +0 -1
  236. package/dist/chunk-3PSLNJDU.js.map +0 -1
  237. package/dist/chunk-42FQ27MQ.js.map +0 -1
  238. package/dist/chunk-4XCHZRUJ.js.map +0 -1
  239. package/dist/chunk-6ZLCPUXS.js.map +0 -1
  240. package/dist/chunk-7AVQIGF6.js.map +0 -1
  241. package/dist/chunk-BXGZFGZ4.js.map +0 -1
  242. package/dist/chunk-DDTS7F5O.js.map +0 -1
  243. package/dist/chunk-EL5VHUGK.js.map +0 -1
  244. package/dist/chunk-FQSQONOU.js.map +0 -1
  245. package/dist/chunk-IOJDYUA7.js.map +0 -1
  246. package/dist/chunk-KRFGO5QH.js.map +0 -1
  247. package/dist/chunk-MS3WPRJR.js.map +0 -1
  248. package/dist/chunk-NPRP3MCV.js.map +0 -1
  249. package/dist/chunk-NY2PYHNC.js.map +0 -1
  250. package/dist/chunk-PKPO3JTZ.js.map +0 -1
  251. package/dist/chunk-PTWADEH3.js.map +0 -1
  252. package/dist/chunk-T7SP3EYR.js.map +0 -1
  253. package/dist/chunk-VNXAF2KE.js.map +0 -1
  254. package/dist/chunk-W2BOPXTI.js +0 -1
  255. package/dist/chunk-W2BOPXTI.js.map +0 -1
  256. package/dist/chunk-WGDEBIP4.js.map +0 -1
  257. /package/dist/{chunk-R6ZCSXKX.js.map → chunk-23MAWVOJ.js.map} +0 -0
  258. /package/dist/{chunk-6MRSX3YK.js.map → chunk-B5Y5GPD5.js.map} +0 -0
  259. /package/dist/{chunk-VP3TIUDF.js.map → chunk-DVTDF5OI.js.map} +0 -0
  260. /package/dist/{chunk-OXD5LFQP.js.map → chunk-G7H6PN7P.js.map} +0 -0
  261. /package/dist/{chunk-446I4EGD.js.map → chunk-J5TBZFBD.js.map} +0 -0
  262. /package/dist/{chunk-QFE5BQH7.js.map → chunk-LTSI7ULC.js.map} +0 -0
  263. /package/dist/{chunk-KNU73RZW.js.map → chunk-NSA5K5G2.js.map} +0 -0
  264. /package/dist/{chunk-MLTPJMH6.js.map → chunk-QQYULEZL.js.map} +0 -0
  265. /package/dist/{chunk-VAZXUK6G.js.map → chunk-SUNCHMML.js.map} +0 -0
  266. /package/dist/{chunk-EP4WVQLX.js.map → chunk-T2U6N3FV.js.map} +0 -0
@@ -20,6 +20,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/utils/memory/index.ts
21
21
  var memory_exports = {};
22
22
  __export(memory_exports, {
23
+ DEFAULT_DECAY_HALF_LIFE_NS: () => DEFAULT_DECAY_HALF_LIFE_NS,
24
+ DEFAULT_DECAY_PERIOD_MS: () => DEFAULT_DECAY_PERIOD_MS,
25
+ ReactiveFactStoreGraph: () => ReactiveFactStoreGraph,
23
26
  admissionLlmJudge: () => admissionLlmJudge,
24
27
  bitemporalQuery: () => bitemporalQuery,
25
28
  collection: () => collection,
@@ -33,10 +36,11 @@ __export(memory_exports, {
33
36
  reactiveFactStore: () => reactiveFactStore,
34
37
  scoringByOutcome: () => scoringByOutcome,
35
38
  shardByTenant: () => shardByTenant,
39
+ simpleFactStore: () => simpleFactStore,
36
40
  vectorIndex: () => vectorIndex
37
41
  });
38
42
  module.exports = __toCommonJS(memory_exports);
39
- var import_core10 = require("@graphrefly/pure-ts/core");
43
+ var import_core11 = require("@graphrefly/pure-ts/core");
40
44
  var import_extra8 = require("@graphrefly/pure-ts/extra");
41
45
  var import_graph3 = require("@graphrefly/pure-ts/graph");
42
46
 
@@ -242,479 +246,534 @@ function currentlyValid(f, asOf) {
242
246
  function lastOf(batch2, prev) {
243
247
  return batch2 != null && batch2.length > 0 ? batch2.at(-1) : prev;
244
248
  }
245
- function reactiveFactStore(config) {
246
- const shardCount = Math.max(1, config.shardCount ?? 4);
247
- const maxIterations = Math.max(1, config.cascadeMaxIterations ?? 8);
248
- const reviewThreshold = config.reviewThreshold ?? 0.3;
249
- const shardBy = config.shardBy ?? ((f) => fnv1a(String(f.id)) % shardCount);
250
- let cascadeIteration = 0;
251
- const processedRoots = /* @__PURE__ */ new Set();
252
- const graph = new import_graph2.Graph("reactive_fact_store");
253
- const events = createAuditLog({
254
- name: "events",
255
- retainedLimit: 1024,
256
- graph
257
- });
258
- const seqCursor = registerCursor(graph, "seq", 0);
259
- const ingestLog = config.recordIngest ? (0, import_extra2.reactiveLog)([], { name: "ingest_log" }) : void 0;
260
- if (ingestLog) graph.addDisposer(() => ingestLog.dispose());
261
- const emptyStore = () => ({ byId: /* @__PURE__ */ new Map() });
262
- const shards = [];
263
- for (let s = 0; s < shardCount; s += 1) {
264
- const shard = (0, import_core2.node)([], {
265
- initial: emptyStore(),
266
- name: `shard_${s}`,
267
- describeKind: "state",
268
- meta: factMeta("factstore", { shard: s })
249
+ var ReactiveFactStoreGraph = class extends import_graph2.Graph {
250
+ // Topic outputs (caller subscribes for custom processing).
251
+ /** Per-shard `state<FactStore<T>>` nodes (length = shard count). */
252
+ shards;
253
+ /** Unified read view across all shards (derived). */
254
+ factStore;
255
+ dependentsIndex;
256
+ answer;
257
+ cascade;
258
+ cascadeOverflow;
259
+ review;
260
+ consolidated;
261
+ events;
262
+ /**
263
+ * Payload-carrying, replayable log of every committed fragment. Present iff
264
+ * {@link ReactiveFactStoreConfig.recordIngest} is `true`. Unlike
265
+ * {@link ReactiveFactStoreGraph.events} (action-only audit), each entry is
266
+ * the full {@link MemoryFragment} — `attachStorage` it for a durable,
267
+ * replayable projection source (see `recordIngest` docs for the recipe).
268
+ */
269
+ ingestLog;
270
+ constructor(config) {
271
+ const shardCount = Math.max(1, config.shardCount ?? 4);
272
+ const maxIterations = Math.max(1, config.cascadeMaxIterations ?? 8);
273
+ const reviewThreshold = config.reviewThreshold ?? 0.3;
274
+ const shardBy = config.shardBy ?? ((f) => fnv1a(String(f.id)) % shardCount);
275
+ let cascadeIteration = 0;
276
+ const processedRoots = /* @__PURE__ */ new Set();
277
+ super("reactive_fact_store");
278
+ const events = createAuditLog({
279
+ name: "events",
280
+ retainedLimit: 1024,
281
+ graph: this
269
282
  });
270
- graph.add(shard, { name: `shard_${s}` });
271
- graph.addDisposer((0, import_extra2.keepalive)(shard));
272
- shards.push(shard);
273
- }
274
- const shardIndexFor = (f) => {
275
- const key = shardBy(f);
276
- const n = typeof key === "number" ? key : fnv1a(String(key));
277
- const idx = (n % shardCount + shardCount) % shardCount;
278
- return idx;
279
- };
280
- const findShardOf = (id) => {
283
+ const seqCursor = registerCursor(this, "seq", 0);
284
+ const ingestLog = config.recordIngest ? (0, import_extra2.reactiveLog)([], { name: "ingest_log" }) : void 0;
285
+ if (ingestLog) this.addDisposer(() => ingestLog.dispose());
286
+ const emptyStore = () => ({ byId: /* @__PURE__ */ new Map() });
287
+ const shards = [];
281
288
  for (let s = 0; s < shardCount; s += 1) {
282
- const fs = shards[s].cache;
283
- if (fs?.byId.has(id)) return s;
284
- }
285
- return -1;
286
- };
287
- const allFacts = () => {
288
- const out2 = /* @__PURE__ */ new Map();
289
- for (const sh of shards) {
290
- const fs = sh.cache;
291
- if (!fs) continue;
292
- for (const [k, v] of fs.byId) out2.set(k, v);
293
- }
294
- return out2;
295
- };
296
- const commitFragment = (f) => {
297
- const idx = shardIndexFor(f);
298
- const cur = shards[idx].cache ?? emptyStore();
299
- const next = new Map(cur.byId);
300
- next.set(f.id, f);
301
- shards[idx].emit({ byId: next });
302
- };
303
- const replaceFragment = (id, mut) => {
304
- const idx = findShardOf(id);
305
- if (idx < 0) return false;
306
- const cur = shards[idx].cache;
307
- const prev = cur.byId.get(id);
308
- if (!prev) return false;
309
- const next = new Map(cur.byId);
310
- next.set(id, mut(prev));
311
- shards[idx].emit({ byId: next });
312
- return true;
313
- };
314
- const dependentsIndex = (0, import_core2.node)([], {
315
- initial: /* @__PURE__ */ new Map(),
316
- name: "dependents_index",
317
- describeKind: "state",
318
- meta: factMeta("factstore", { role: "dependents_index" })
319
- });
320
- graph.add(dependentsIndex, { name: "dependents_index" });
321
- graph.addDisposer((0, import_extra2.keepalive)(dependentsIndex));
322
- const indexFragment = (f, deps) => {
323
- const cur = dependentsIndex.cache;
324
- const next = /* @__PURE__ */ new Map();
325
- for (const [k, v] of cur) next.set(k, [...v]);
326
- for (const src of deps) {
327
- const bucket = next.get(src) ?? [];
328
- if (!bucket.includes(f.id)) bucket.push(f.id);
329
- next.set(src, bucket);
289
+ const shard = (0, import_core2.node)([], {
290
+ initial: emptyStore(),
291
+ name: `shard_${s}`,
292
+ describeKind: "state",
293
+ meta: factMeta("factstore", { shard: s })
294
+ });
295
+ this.add(shard, { name: `shard_${s}` });
296
+ this.addDisposer((0, import_extra2.keepalive)(shard));
297
+ shards.push(shard);
330
298
  }
331
- dependentsIndex.emit(next);
332
- };
333
- const factStore = (0, import_core2.node)(
334
- shards,
335
- (batchData, actions, ctx) => {
336
- void batchData;
337
- void ctx;
338
- actions.emit({ byId: allFacts() });
339
- },
340
- {
341
- name: "fact_store",
342
- describeKind: "derived",
343
- initial: emptyStore(),
344
- meta: factMeta("factstore", { role: "read_view" }),
345
- // F10a: `allFacts()` builds a fresh Map every detector retrigger.
346
- // Fragments are immutable (replaced wholesale on mutation), so a
347
- // same-size + per-key-identity check is a sound structural equality
348
- // that stops `factStore` (and its `review` dependent) from re-firing
349
- // every cascade wave when nothing actually changed.
350
- equals: (a, b) => {
351
- if (a === b) return true;
352
- if (a.byId.size !== b.byId.size) return false;
353
- for (const [k, v] of a.byId) {
354
- if (b.byId.get(k) !== v) return false;
355
- }
356
- return true;
299
+ const shardIndexFor = (f) => {
300
+ const key = shardBy(f);
301
+ const n = typeof key === "number" ? key : fnv1a(String(key));
302
+ const idx = (n % shardCount + shardCount) % shardCount;
303
+ return idx;
304
+ };
305
+ const findShardOf = (id) => {
306
+ for (let s = 0; s < shardCount; s += 1) {
307
+ const fs = shards[s].cache;
308
+ if (fs?.byId.has(id)) return s;
357
309
  }
358
- }
359
- );
360
- graph.add(factStore, { name: "fact_store" });
361
- graph.addDisposer((0, import_extra2.keepalive)(factStore));
362
- const extractOp = (0, import_core2.node)(
363
- config.admissionFilter ? [config.ingest, config.admissionFilter] : [config.ingest],
364
- (batchData, actions, ctx) => {
365
- const f = lastOf(batchData[0], ctx.prevData[0]);
366
- if (f == null) {
367
- actions.emit(null);
368
- return;
310
+ return -1;
311
+ };
312
+ const allFacts = () => {
313
+ const out = /* @__PURE__ */ new Map();
314
+ for (const sh of shards) {
315
+ const fs = sh.cache;
316
+ if (!fs) continue;
317
+ for (const [k, v] of fs.byId) out.set(k, v);
369
318
  }
370
- if (config.admissionFilter) {
371
- const filter = lastOf(batchData[1], ctx.prevData[1]);
372
- if (filter && !filter(f)) {
319
+ return out;
320
+ };
321
+ const commitFragment = (f) => {
322
+ const idx = shardIndexFor(f);
323
+ const cur = shards[idx].cache ?? emptyStore();
324
+ const next = new Map(cur.byId);
325
+ next.set(f.id, f);
326
+ shards[idx].emit({ byId: next });
327
+ };
328
+ const replaceFragment = (id, mut) => {
329
+ const idx = findShardOf(id);
330
+ if (idx < 0) return false;
331
+ const cur = shards[idx].cache;
332
+ const prev = cur.byId.get(id);
333
+ if (!prev) return false;
334
+ const next = new Map(cur.byId);
335
+ next.set(id, mut(prev));
336
+ shards[idx].emit({ byId: next });
337
+ return true;
338
+ };
339
+ const dependentsIndex = (0, import_core2.node)([], {
340
+ initial: /* @__PURE__ */ new Map(),
341
+ name: "dependents_index",
342
+ describeKind: "state",
343
+ meta: factMeta("factstore", { role: "dependents_index" })
344
+ });
345
+ this.add(dependentsIndex, { name: "dependents_index" });
346
+ this.addDisposer((0, import_extra2.keepalive)(dependentsIndex));
347
+ const indexFragment = (f, deps) => {
348
+ const cur = dependentsIndex.cache;
349
+ const next = /* @__PURE__ */ new Map();
350
+ for (const [k, v] of cur) next.set(k, [...v]);
351
+ for (const src of deps) {
352
+ const bucket = next.get(src) ?? [];
353
+ if (!bucket.includes(f.id)) bucket.push(f.id);
354
+ next.set(src, bucket);
355
+ }
356
+ dependentsIndex.emit(next);
357
+ };
358
+ const factStore = (0, import_core2.node)(
359
+ shards,
360
+ (batchData, actions, ctx) => {
361
+ void batchData;
362
+ void ctx;
363
+ actions.emit({ byId: allFacts() });
364
+ },
365
+ {
366
+ name: "fact_store",
367
+ describeKind: "derived",
368
+ initial: emptyStore(),
369
+ meta: factMeta("factstore", { role: "read_view" }),
370
+ // F10a: `allFacts()` builds a fresh Map every detector retrigger.
371
+ // Fragments are immutable (replaced wholesale on mutation), so a
372
+ // same-size + per-key-identity check is a sound structural equality
373
+ // that stops `factStore` (and its `review` dependent) from re-firing
374
+ // every cascade wave when nothing actually changed.
375
+ equals: (a, b) => {
376
+ if (a === b) return true;
377
+ if (a.byId.size !== b.byId.size) return false;
378
+ for (const [k, v] of a.byId) {
379
+ if (b.byId.get(k) !== v) return false;
380
+ }
381
+ return true;
382
+ }
383
+ }
384
+ );
385
+ this.add(factStore, { name: "fact_store" });
386
+ this.addDisposer((0, import_extra2.keepalive)(factStore));
387
+ const extractOp = (0, import_core2.node)(
388
+ config.admissionFilter ? [config.ingest, config.admissionFilter] : [config.ingest],
389
+ (batchData, actions, ctx) => {
390
+ const f = lastOf(batchData[0], ctx.prevData[0]);
391
+ if (f == null) {
373
392
  actions.emit(null);
374
393
  return;
375
394
  }
376
- }
377
- const deps = config.extractDependencies(f);
378
- cascadeIteration = 0;
379
- processedRoots.delete(f.id);
380
- commitFragment(f);
381
- indexFragment(f, deps);
382
- actions.emit(f);
383
- },
384
- {
385
- name: "extract_op",
386
- describeKind: "derived",
387
- meta: factMeta("extract")
388
- }
389
- );
390
- graph.add(extractOp, { name: "extract_op" });
391
- graph.addDisposer((0, import_extra2.keepalive)(extractOp));
392
- const invalidationDetector = (0, import_core2.node)(
393
- [...shards],
394
- (batchData, actions, ctx) => {
395
- void batchData;
396
- void ctx;
397
- const facts = allFacts();
398
- const index = dependentsIndex.cache;
399
- const out2 = [];
400
- const seen = /* @__PURE__ */ new Set();
401
- for (const f of facts.values()) {
402
- const obsolete = f.validTo !== void 0;
403
- if (!obsolete) continue;
404
- if (processedRoots.has(f.id)) continue;
405
- const dependents = index.get(f.id) ?? [];
406
- for (const dep of dependents) {
407
- const depFact = facts.get(dep);
408
- if (!depFact || depFact.validTo !== void 0) continue;
409
- const k = `${f.id}->${dep}`;
410
- if (seen.has(k)) continue;
411
- seen.add(k);
412
- out2.push({
413
- factId: dep,
414
- rootFactId: f.id,
415
- reason: "obsolete",
416
- // `obsolete` guard above guarantees `f.validTo` is set.
417
- rootValidTo: f.validTo,
418
- iteration: cascadeIteration + 1,
419
- causalReason: `dependentsIndex[${f.id}] \u2192 ${dep} (obsolete: validTo set)`
420
- });
395
+ if (config.admissionFilter) {
396
+ const filter = lastOf(batchData[1], ctx.prevData[1]);
397
+ if (filter && !filter(f)) {
398
+ actions.emit(null);
399
+ return;
400
+ }
421
401
  }
422
- processedRoots.add(f.id);
423
- }
424
- if (out2.length === 0) {
402
+ const deps = config.extractDependencies(f);
425
403
  cascadeIteration = 0;
404
+ processedRoots.delete(f.id);
405
+ commitFragment(f);
406
+ indexFragment(f, deps);
407
+ actions.emit(f);
408
+ },
409
+ {
410
+ name: "extract_op",
411
+ describeKind: "derived",
412
+ meta: factMeta("extract")
426
413
  }
427
- actions.emit(out2);
428
- },
429
- {
430
- name: "invalidation_detector",
431
- describeKind: "derived",
432
- initial: [],
433
- meta: factMeta("invalidation", { cycle: "cascade" })
434
- }
435
- );
436
- graph.add(invalidationDetector, { name: "invalidation_detector" });
437
- graph.addDisposer((0, import_extra2.keepalive)(invalidationDetector));
438
- const cascade = (0, import_core2.node)(
439
- [invalidationDetector],
440
- (batchData, actions, ctx) => {
441
- const evts = lastOf(batchData[0], ctx.prevData[0]) ?? [];
442
- actions.emit(evts);
443
- },
444
- {
445
- name: "cascade",
446
- describeKind: "derived",
447
- initial: [],
448
- meta: factMeta("cascade_topic", { cycle: "cascade" })
449
- }
450
- );
451
- graph.add(cascade, { name: "cascade" });
452
- graph.addDisposer((0, import_extra2.keepalive)(cascade));
453
- const cascadeOverflow = (0, import_core2.node)([], {
454
- initial: null,
455
- name: "cascade_overflow",
456
- describeKind: "state",
457
- meta: factMeta("cascade_overflow")
458
- });
459
- graph.add(cascadeOverflow, { name: "cascade_overflow" });
460
- graph.addDisposer((0, import_extra2.keepalive)(cascadeOverflow));
461
- const cascadeProcessor = (0, import_core2.node)(
462
- [cascade],
463
- (batchData, actions, ctx) => {
464
- const evts = lastOf(batchData[0], ctx.prevData[0]) ?? [];
465
- if (evts.length === 0) {
466
- actions.emit([]);
467
- return;
468
- }
469
- const byId = /* @__PURE__ */ new Map();
470
- for (const e of evts) if (!byId.has(e.factId)) byId.set(e.factId, e);
471
- cascadeIteration += 1;
472
- if (cascadeIteration > maxIterations) {
473
- const sample = [...byId.keys()].slice(0, OVERFLOW_SAMPLE_SIZE);
474
- const rootFactId = evts[0]?.rootFactId ?? "";
475
- cascadeOverflow.emit({
476
- droppedCount: byId.size,
477
- sample,
478
- rootFactId
479
- });
480
- events.append({
481
- action: "overflow",
482
- reason: "cascade",
483
- id: rootFactId,
484
- t_ns: (0, import_core2.wallClockNs)(),
485
- seq: bumpCursor(seqCursor)
486
- });
487
- actions.emit([]);
488
- return;
489
- }
490
- for (const [id, e] of byId) {
491
- replaceFragment(
492
- id,
493
- (prev) => prev.validTo !== void 0 ? prev : { ...prev, validTo: e.rootValidTo }
494
- );
414
+ );
415
+ this.add(extractOp, { name: "extract_op" });
416
+ this.addDisposer((0, import_extra2.keepalive)(extractOp));
417
+ const invalidationDetector = (0, import_core2.node)(
418
+ [...shards],
419
+ (batchData, actions, ctx) => {
420
+ void batchData;
421
+ void ctx;
422
+ const facts = allFacts();
423
+ const index = dependentsIndex.cache;
424
+ const out = [];
425
+ const seen = /* @__PURE__ */ new Set();
426
+ for (const f of facts.values()) {
427
+ const obsolete = f.validTo !== void 0;
428
+ if (!obsolete) continue;
429
+ if (processedRoots.has(f.id)) continue;
430
+ const dependents = index.get(f.id) ?? [];
431
+ for (const dep of dependents) {
432
+ const depFact = facts.get(dep);
433
+ if (!depFact || depFact.validTo !== void 0) continue;
434
+ const k = `${f.id}->${dep}`;
435
+ if (seen.has(k)) continue;
436
+ seen.add(k);
437
+ out.push({
438
+ factId: dep,
439
+ rootFactId: f.id,
440
+ reason: "obsolete",
441
+ // `obsolete` guard above guarantees `f.validTo` is set.
442
+ rootValidTo: f.validTo,
443
+ iteration: cascadeIteration + 1,
444
+ causalReason: `dependentsIndex[${f.id}] \u2192 ${dep} (obsolete: validTo set)`
445
+ });
446
+ }
447
+ processedRoots.add(f.id);
448
+ }
449
+ if (out.length === 0) {
450
+ cascadeIteration = 0;
451
+ }
452
+ actions.emit(out);
453
+ },
454
+ {
455
+ name: "invalidation_detector",
456
+ describeKind: "derived",
457
+ initial: [],
458
+ meta: factMeta("invalidation", { cycle: "cascade" })
495
459
  }
496
- actions.emit([...byId.values()]);
497
- },
498
- {
499
- name: "cascade_processor",
500
- describeKind: "derived",
501
- initial: [],
502
- meta: factMeta("cascade_processor", { cycle: "cascade" })
503
- }
504
- );
505
- graph.add(cascadeProcessor, { name: "cascade_processor" });
506
- graph.addDisposer((0, import_extra2.keepalive)(cascadeProcessor));
507
- const review = (0, import_core2.node)(
508
- [factStore],
509
- (batchData, actions, ctx) => {
510
- const fs = lastOf(batchData[0], ctx.prevData[0]);
511
- if (fs == null) {
512
- actions.emit(null);
513
- return;
460
+ );
461
+ this.add(invalidationDetector, { name: "invalidation_detector" });
462
+ this.addDisposer((0, import_extra2.keepalive)(invalidationDetector));
463
+ const cascade = (0, import_core2.node)(
464
+ [invalidationDetector],
465
+ (batchData, actions, ctx) => {
466
+ const evts = lastOf(batchData[0], ctx.prevData[0]) ?? [];
467
+ actions.emit(evts);
468
+ },
469
+ {
470
+ name: "cascade",
471
+ describeKind: "derived",
472
+ initial: [],
473
+ meta: factMeta("cascade_topic", { cycle: "cascade" })
514
474
  }
515
- for (const f of fs.byId.values()) {
516
- if (f.confidence < reviewThreshold && f.validTo === void 0) {
517
- actions.emit({
518
- factId: f.id,
519
- confidence: f.confidence,
520
- threshold: reviewThreshold
475
+ );
476
+ this.add(cascade, { name: "cascade" });
477
+ this.addDisposer((0, import_extra2.keepalive)(cascade));
478
+ const cascadeOverflow = (0, import_core2.node)([], {
479
+ initial: null,
480
+ name: "cascade_overflow",
481
+ describeKind: "state",
482
+ meta: factMeta("cascade_overflow")
483
+ });
484
+ this.add(cascadeOverflow, { name: "cascade_overflow" });
485
+ this.addDisposer((0, import_extra2.keepalive)(cascadeOverflow));
486
+ const cascadeProcessor = (0, import_core2.node)(
487
+ [cascade],
488
+ (batchData, actions, ctx) => {
489
+ const evts = lastOf(batchData[0], ctx.prevData[0]) ?? [];
490
+ if (evts.length === 0) {
491
+ actions.emit([]);
492
+ return;
493
+ }
494
+ const byId = /* @__PURE__ */ new Map();
495
+ for (const e of evts) if (!byId.has(e.factId)) byId.set(e.factId, e);
496
+ cascadeIteration += 1;
497
+ if (cascadeIteration > maxIterations) {
498
+ const sample = [...byId.keys()].slice(0, OVERFLOW_SAMPLE_SIZE);
499
+ const rootFactId = evts[0]?.rootFactId ?? "";
500
+ cascadeOverflow.emit({
501
+ droppedCount: byId.size,
502
+ sample,
503
+ rootFactId
521
504
  });
505
+ events.append({
506
+ action: "overflow",
507
+ reason: "cascade",
508
+ id: rootFactId,
509
+ t_ns: (0, import_core2.wallClockNs)(),
510
+ seq: bumpCursor(seqCursor)
511
+ });
512
+ actions.emit([]);
522
513
  return;
523
514
  }
515
+ for (const [id, e] of byId) {
516
+ replaceFragment(
517
+ id,
518
+ (prev) => prev.validTo !== void 0 ? prev : { ...prev, validTo: e.rootValidTo }
519
+ );
520
+ }
521
+ actions.emit([...byId.values()]);
522
+ },
523
+ {
524
+ name: "cascade_processor",
525
+ describeKind: "derived",
526
+ initial: [],
527
+ meta: factMeta("cascade_processor", { cycle: "cascade" })
524
528
  }
525
- actions.emit(null);
526
- },
527
- {
528
- name: "review",
529
- describeKind: "derived",
530
- initial: null,
531
- meta: factMeta("review"),
532
- // F10a: dedupe on the requested factId (null === no request) so a
533
- // stable low-confidence fact does not re-emit a review every wave.
534
- equals: (a, b) => (a?.factId ?? null) === (b?.factId ?? null)
535
- }
536
- );
537
- graph.add(review, { name: "review" });
538
- graph.addDisposer((0, import_extra2.keepalive)(review));
539
- if (config.outcome) {
540
- const outcomeProcessor = (0, import_core2.node)(
541
- config.scoring ? [config.outcome, config.scoring] : [config.outcome],
529
+ );
530
+ this.add(cascadeProcessor, { name: "cascade_processor" });
531
+ this.addDisposer((0, import_extra2.keepalive)(cascadeProcessor));
532
+ const review = (0, import_core2.node)(
533
+ [factStore],
542
534
  (batchData, actions, ctx) => {
543
- const sig = lastOf(batchData[0], ctx.prevData[0]);
544
- if (sig == null) {
535
+ const fs = lastOf(batchData[0], ctx.prevData[0]);
536
+ if (fs == null) {
545
537
  actions.emit(null);
546
538
  return;
547
539
  }
548
- replaceFragment(sig.factId, (prev) => {
549
- let nextConf = prev.confidence;
550
- if (config.scoring) {
551
- const policy2 = lastOf(batchData[1], ctx.prevData[1]);
552
- if (policy2) {
553
- nextConf = policy2(prev, makeReadHandle(allFacts()));
554
- }
555
- } else {
556
- nextConf = Math.max(0, Math.min(1, prev.confidence + sig.reward));
540
+ for (const f of fs.byId.values()) {
541
+ if (f.confidence < reviewThreshold && f.validTo === void 0) {
542
+ actions.emit({
543
+ factId: f.id,
544
+ confidence: f.confidence,
545
+ threshold: reviewThreshold
546
+ });
547
+ return;
557
548
  }
558
- return { ...prev, confidence: nextConf };
559
- });
560
- actions.emit(sig);
549
+ }
550
+ actions.emit(null);
561
551
  },
562
552
  {
563
- name: "outcome_processor",
553
+ name: "review",
564
554
  describeKind: "derived",
565
555
  initial: null,
566
- meta: factMeta("outcome")
556
+ meta: factMeta("review"),
557
+ // F10a: dedupe on the requested factId (null === no request) so a
558
+ // stable low-confidence fact does not re-emit a review every wave.
559
+ equals: (a, b) => (a?.factId ?? null) === (b?.factId ?? null)
567
560
  }
568
561
  );
569
- graph.add(outcomeProcessor, { name: "outcome_processor" });
570
- graph.addDisposer((0, import_extra2.keepalive)(outcomeProcessor));
571
- }
572
- const answer = (0, import_core2.node)(
573
- config.query ? [config.query, factStore] : [factStore],
574
- (batchData, actions, ctx) => {
575
- if (!config.query) {
576
- actions.emit(null);
577
- return;
578
- }
579
- const q = lastOf(batchData[0], ctx.prevData[0]);
580
- const fs = lastOf(batchData[1], ctx.prevData[1]);
581
- if (q == null) {
582
- actions.emit(null);
583
- return;
584
- }
585
- const store = fs ?? emptyStore();
586
- let results = [...store.byId.values()].filter((f) => {
587
- if (q.tags && q.tags.length > 0 && !q.tags.some((t) => f.tags.includes(t))) {
588
- return false;
562
+ this.add(review, { name: "review" });
563
+ this.addDisposer((0, import_extra2.keepalive)(review));
564
+ if (config.outcome) {
565
+ const outcomeProcessor = (0, import_core2.node)(
566
+ config.scoring ? [config.outcome, config.scoring] : [config.outcome],
567
+ (batchData, actions, ctx) => {
568
+ const sig = lastOf(batchData[0], ctx.prevData[0]);
569
+ if (sig == null) {
570
+ actions.emit(null);
571
+ return;
572
+ }
573
+ replaceFragment(sig.factId, (prev) => {
574
+ let nextConf = prev.confidence;
575
+ if (config.scoring) {
576
+ const policy2 = lastOf(batchData[1], ctx.prevData[1]);
577
+ if (policy2) {
578
+ nextConf = policy2(prev, makeReadHandle(allFacts()));
579
+ }
580
+ } else {
581
+ nextConf = Math.max(0, Math.min(1, prev.confidence + sig.reward));
582
+ }
583
+ return { ...prev, confidence: nextConf };
584
+ });
585
+ actions.emit(sig);
586
+ },
587
+ {
588
+ name: "outcome_processor",
589
+ describeKind: "derived",
590
+ initial: null,
591
+ meta: factMeta("outcome")
589
592
  }
590
- if (q.minConfidence !== void 0 && f.confidence < q.minConfidence) return false;
591
- if (!currentlyValid(f, q.asOf)) return false;
592
- return true;
593
- });
594
- results.sort((a, b) => b.confidence - a.confidence || Number(b.t_ns - a.t_ns));
595
- if (q.limit !== void 0) results = results.slice(0, Math.max(0, q.limit));
596
- actions.emit({ query: q, results });
597
- },
598
- {
599
- name: "answer",
600
- describeKind: "derived",
601
- initial: null,
602
- meta: factMeta("query", { role: "output" })
593
+ );
594
+ this.add(outcomeProcessor, { name: "outcome_processor" });
595
+ this.addDisposer((0, import_extra2.keepalive)(outcomeProcessor));
603
596
  }
604
- );
605
- graph.add(answer, { name: "answer" });
606
- graph.addDisposer((0, import_extra2.keepalive)(answer));
607
- const consolidated = (0, import_core2.node)(
608
- config.consolidateTrigger ? [config.consolidateTrigger] : [],
609
- (batchData, actions, ctx) => {
610
- void batchData;
611
- void ctx;
612
- if (!config.consolidateTrigger || !config.consolidate) {
613
- actions.emit([]);
614
- return;
615
- }
616
- const fragments = config.consolidate(makeReadHandle(allFacts()));
617
- for (const f of fragments) {
618
- const deps = config.extractDependencies(f);
619
- processedRoots.delete(f.id);
620
- commitFragment(f);
621
- indexFragment(f, deps);
622
- events.append({
623
- action: "consolidate",
624
- id: f.id,
625
- t_ns: (0, import_core2.wallClockNs)(),
626
- seq: bumpCursor(seqCursor)
597
+ const answer = (0, import_core2.node)(
598
+ config.query ? [config.query, factStore] : [factStore],
599
+ (batchData, actions, ctx) => {
600
+ if (!config.query) {
601
+ actions.emit(null);
602
+ return;
603
+ }
604
+ const q = lastOf(batchData[0], ctx.prevData[0]);
605
+ const fs = lastOf(batchData[1], ctx.prevData[1]);
606
+ if (q == null) {
607
+ actions.emit(null);
608
+ return;
609
+ }
610
+ const store = fs ?? emptyStore();
611
+ let results = [...store.byId.values()].filter((f) => {
612
+ if (q.tags && q.tags.length > 0 && !q.tags.some((t) => f.tags.includes(t))) {
613
+ return false;
614
+ }
615
+ if (q.minConfidence !== void 0 && f.confidence < q.minConfidence) return false;
616
+ if (!currentlyValid(f, q.asOf)) return false;
617
+ return true;
627
618
  });
619
+ results.sort((a, b) => b.confidence - a.confidence || Number(b.t_ns - a.t_ns));
620
+ if (q.limit !== void 0) results = results.slice(0, Math.max(0, q.limit));
621
+ actions.emit({ query: q, results });
622
+ },
623
+ {
624
+ name: "answer",
625
+ describeKind: "derived",
626
+ initial: null,
627
+ meta: factMeta("query", { role: "output" })
628
628
  }
629
- actions.emit(fragments);
630
- },
631
- {
632
- name: "consolidated",
633
- describeKind: "derived",
634
- initial: [],
635
- meta: factMeta("consolidator")
636
- }
637
- );
638
- graph.add(consolidated, { name: "consolidated" });
639
- graph.addDisposer((0, import_extra2.keepalive)(consolidated));
640
- if (config.decayTrigger) {
641
- const decayProcessor = (0, import_core2.node)(
642
- config.decay ? [config.decayTrigger, config.decay] : [config.decayTrigger],
629
+ );
630
+ this.add(answer, { name: "answer" });
631
+ this.addDisposer((0, import_extra2.keepalive)(answer));
632
+ const consolidated = (0, import_core2.node)(
633
+ config.consolidateTrigger ? [config.consolidateTrigger] : [],
643
634
  (batchData, actions, ctx) => {
644
- const policy2 = config.decay ? lastOf(batchData[1], ctx.prevData[1]) : void 0;
645
- if (!policy2) {
635
+ void batchData;
636
+ void ctx;
637
+ if (!config.consolidateTrigger || !config.consolidate) {
646
638
  actions.emit([]);
647
639
  return;
648
640
  }
649
- const now = BigInt((0, import_core2.monotonicNs)());
650
- const changes = [];
651
- for (const f of allFacts().values()) {
652
- if (f.validTo !== void 0) continue;
653
- const ageNs = now - f.t_ns;
654
- const raw = policy2(f.confidence, ageNs);
655
- if (!Number.isFinite(raw)) continue;
656
- const next = raw < 0 ? 0 : raw > 1 ? 1 : raw;
657
- if (next === f.confidence) continue;
658
- changes.push({ id: f.id, next });
641
+ const fragments = config.consolidate(makeReadHandle(allFacts()));
642
+ for (const f of fragments) {
643
+ const deps = config.extractDependencies(f);
644
+ processedRoots.delete(f.id);
645
+ commitFragment(f);
646
+ indexFragment(f, deps);
647
+ events.append({
648
+ action: "consolidate",
649
+ id: f.id,
650
+ t_ns: (0, import_core2.wallClockNs)(),
651
+ seq: bumpCursor(seqCursor)
652
+ });
659
653
  }
660
- const decayed = [];
661
- for (const { id, next } of changes) {
662
- const idx = findShardOf(id);
663
- const fs = idx < 0 ? void 0 : shards[idx].cache;
664
- const live = fs?.byId.get(id);
665
- if (!live || live.validTo !== void 0) continue;
666
- replaceFragment(
667
- id,
668
- (prev) => prev.validTo !== void 0 ? prev : { ...prev, confidence: next }
669
- );
670
- decayed.push({ ...live, confidence: next });
654
+ actions.emit(fragments);
655
+ },
656
+ {
657
+ name: "consolidated",
658
+ describeKind: "derived",
659
+ initial: [],
660
+ // Inspection completeness (COMPOSITION-GUIDE §24 "make the
661
+ // invisible edge visible"): `consolidated` write-backs feed the
662
+ // bounded cascade store (commit shard emit
663
+ // `invalidationDetector`) exactly like `cascadeProcessor`, but
664
+ // is NOT a cascade-cycle node. `feeds:"cascade"` surfaces it as
665
+ // a cascade-store mutator in `describe()`/`explain()`;
666
+ // `drivesRoot:false` — by the consolidator contract successors
667
+ // are fresh live facts (no `validTo`), so on the contract path
668
+ // they do not root the cascade. (An out-of-contract `consolidate`
669
+ // that emits a `validTo`-set fragment WOULD root it via the
670
+ // detector — the tag reflects the documented contract, not a
671
+ // structural impossibility. Contrast `decay_processor` below,
672
+ // whose `drivesRoot:false` IS structurally provable.)
673
+ meta: factMeta("consolidator", { feeds: "cascade", drivesRoot: false })
674
+ }
675
+ );
676
+ this.add(consolidated, { name: "consolidated" });
677
+ this.addDisposer((0, import_extra2.keepalive)(consolidated));
678
+ if (config.decayTrigger) {
679
+ const decayProcessor = (0, import_core2.node)(
680
+ config.decay ? [config.decayTrigger, config.decay] : [config.decayTrigger],
681
+ (batchData, actions, ctx) => {
682
+ const policy2 = config.decay ? lastOf(batchData[1], ctx.prevData[1]) : void 0;
683
+ if (!policy2) {
684
+ actions.emit([]);
685
+ return;
686
+ }
687
+ const now = BigInt((0, import_core2.monotonicNs)());
688
+ const changes = [];
689
+ for (const f of allFacts().values()) {
690
+ if (f.validTo !== void 0) continue;
691
+ const ageNs = now - f.t_ns;
692
+ const raw = policy2(f.confidence, ageNs);
693
+ if (!Number.isFinite(raw)) continue;
694
+ const next = raw < 0 ? 0 : raw > 1 ? 1 : raw;
695
+ if (next === f.confidence) continue;
696
+ changes.push({ id: f.id, next });
697
+ }
698
+ const decayed = [];
699
+ for (const { id, next } of changes) {
700
+ const idx = findShardOf(id);
701
+ const fs = idx < 0 ? void 0 : shards[idx].cache;
702
+ const live = fs?.byId.get(id);
703
+ if (!live || live.validTo !== void 0) continue;
704
+ replaceFragment(
705
+ id,
706
+ (prev) => prev.validTo !== void 0 ? prev : { ...prev, confidence: next }
707
+ );
708
+ decayed.push({ ...live, confidence: next });
709
+ }
710
+ if (decayed.length > 0) {
711
+ events.append({
712
+ action: "decay",
713
+ t_ns: (0, import_core2.wallClockNs)(),
714
+ seq: bumpCursor(seqCursor),
715
+ count: decayed.length
716
+ });
717
+ }
718
+ actions.emit(decayed);
719
+ },
720
+ {
721
+ name: "decay_processor",
722
+ describeKind: "derived",
723
+ initial: [],
724
+ // Inspection completeness (same convention as `consolidated`
725
+ // above — kept uniform): `decay_processor` write-backs feed
726
+ // the cascade store via `replaceFragment` → shard emit →
727
+ // `invalidationDetector`. `feeds:"cascade"` surfaces it as a
728
+ // cascade-store mutator; `drivesRoot:false` — decay only
729
+ // mutates `confidence`, never `validTo`, and the detector
730
+ // roots on `validTo` only, so it provably cannot root.
731
+ meta: factMeta("decay", { feeds: "cascade", drivesRoot: false })
671
732
  }
672
- if (decayed.length > 0) {
733
+ );
734
+ this.add(decayProcessor, { name: "decay_processor" });
735
+ this.addDisposer((0, import_extra2.keepalive)(decayProcessor));
736
+ }
737
+ const ingestAudit = (0, import_core2.node)(
738
+ [extractOp],
739
+ (batchData, actions, ctx) => {
740
+ const f = lastOf(batchData[0], ctx.prevData[0]);
741
+ if (f != null) {
673
742
  events.append({
674
- action: "decay",
743
+ action: "ingest",
744
+ id: f.id,
675
745
  t_ns: (0, import_core2.wallClockNs)(),
676
746
  seq: bumpCursor(seqCursor)
677
747
  });
748
+ ingestLog?.append(f);
678
749
  }
679
- actions.emit(decayed);
750
+ actions.emit(f ?? null);
680
751
  },
681
752
  {
682
- name: "decay_processor",
753
+ name: "_ingest_audit",
683
754
  describeKind: "derived",
684
- initial: [],
685
- meta: factMeta("decay")
755
+ initial: null,
756
+ meta: factMeta("audit")
686
757
  }
687
758
  );
688
- graph.add(decayProcessor, { name: "decay_processor" });
689
- graph.addDisposer((0, import_extra2.keepalive)(decayProcessor));
759
+ this.add(ingestAudit, { name: "_ingest_audit" });
760
+ this.addDisposer((0, import_extra2.keepalive)(ingestAudit));
761
+ this.shards = shards;
762
+ this.factStore = factStore;
763
+ this.dependentsIndex = dependentsIndex;
764
+ this.answer = answer;
765
+ this.cascade = cascade;
766
+ this.cascadeOverflow = cascadeOverflow;
767
+ this.review = review;
768
+ this.consolidated = consolidated;
769
+ this.events = events;
770
+ if (ingestLog) this.ingestLog = ingestLog;
690
771
  }
691
- const ingestAudit = (0, import_core2.node)(
692
- [extractOp],
693
- (batchData, actions, ctx) => {
694
- const f = lastOf(batchData[0], ctx.prevData[0]);
695
- if (f != null) {
696
- events.append({
697
- action: "ingest",
698
- id: f.id,
699
- t_ns: (0, import_core2.wallClockNs)(),
700
- seq: bumpCursor(seqCursor)
701
- });
702
- ingestLog?.append(f);
703
- }
704
- actions.emit(f ?? null);
705
- },
706
- {
707
- name: "_ingest_audit",
708
- describeKind: "derived",
709
- initial: null,
710
- meta: factMeta("audit")
711
- }
712
- );
713
- graph.add(ingestAudit, { name: "_ingest_audit" });
714
- graph.addDisposer((0, import_extra2.keepalive)(ingestAudit));
715
- function itemNode(id) {
772
+ // ── itemNode reactive read ───────────────────────────────────────────
773
+ /** Reactive read: a single fact by id (SENTINEL until the fact exists). */
774
+ itemNode(id) {
716
775
  return (0, import_core2.node)(
717
- [factStore],
776
+ [this.factStore],
718
777
  (batchData, actions, ctx) => {
719
778
  const fs = lastOf(batchData[0], ctx.prevData[0]);
720
779
  actions.emit(fs?.byId.get(id));
@@ -726,20 +785,9 @@ function reactiveFactStore(config) {
726
785
  }
727
786
  );
728
787
  }
729
- const out = Object.assign(graph, {
730
- shards,
731
- factStore,
732
- dependentsIndex,
733
- answer,
734
- cascade,
735
- cascadeOverflow,
736
- review,
737
- consolidated,
738
- events,
739
- ...ingestLog ? { ingestLog } : {},
740
- itemNode
741
- });
742
- return out;
788
+ };
789
+ function reactiveFactStore(config) {
790
+ return new ReactiveFactStoreGraph(config);
743
791
  }
744
792
 
745
793
  // src/utils/memory/persistent-fact-store.ts
@@ -1158,14 +1206,60 @@ function shardByTenant(tenantOf, opts = {}) {
1158
1206
  return { shardBy: (f) => tenantOf(f), shardCount };
1159
1207
  }
1160
1208
 
1209
+ // src/utils/memory/simple-fact-store.ts
1210
+ var import_core10 = require("@graphrefly/pure-ts/core");
1211
+ var DEFAULT_DECAY_HALF_LIFE_NS = 604800000000000n;
1212
+ var DEFAULT_DECAY_PERIOD_MS = 36e5;
1213
+ function simpleFactStore(opts = {}) {
1214
+ const ingest = (0, import_core10.node)([], { initial: void 0 });
1215
+ const extractDependencies = opts.extractDependencies ?? (() => []);
1216
+ const consolidationCfg = opts.consolidate ? consolidationRem(opts.consolidate) : void 0;
1217
+ const baseCfg = {
1218
+ ingest,
1219
+ extractDependencies,
1220
+ ...consolidationCfg ?? {}
1221
+ };
1222
+ const mem = opts.storage ? persistentReactiveFactStore({
1223
+ ...baseCfg,
1224
+ storage: opts.storage,
1225
+ ...opts.persistName !== void 0 ? { persistName: opts.persistName } : {},
1226
+ ...opts.codec !== void 0 ? { codec: opts.codec } : {}
1227
+ }) : reactiveFactStore(baseCfg);
1228
+ if (opts.decay !== false) {
1229
+ const d = opts.decay ?? {};
1230
+ decayExponential(mem, ingest, {
1231
+ ...d,
1232
+ halfLifeNs: d.halfLifeNs ?? DEFAULT_DECAY_HALF_LIFE_NS,
1233
+ periodMs: d.periodMs ?? DEFAULT_DECAY_PERIOD_MS
1234
+ });
1235
+ }
1236
+ const remember = (id, payload, ro) => {
1237
+ const fragment = {
1238
+ id,
1239
+ payload,
1240
+ t_ns: BigInt((0, import_core10.monotonicNs)()),
1241
+ confidence: ro?.confidence ?? 1,
1242
+ tags: ro?.tags ?? [],
1243
+ sources: ro?.sources ?? [],
1244
+ ...ro?.validTo !== void 0 ? { validTo: ro.validTo } : {},
1245
+ ...ro?.validFrom !== void 0 ? { validFrom: ro.validFrom } : {},
1246
+ ...ro?.provenance !== void 0 ? { provenance: ro.provenance } : {}
1247
+ };
1248
+ ingest.emit(fragment);
1249
+ };
1250
+ const out = mem;
1251
+ out.remember = remember;
1252
+ return out;
1253
+ }
1254
+
1161
1255
  // src/utils/memory/index.ts
1162
1256
  var NS_PER_SEC = 1e9;
1163
1257
  function memoryMeta(kind, extra) {
1164
1258
  return domainMeta("memory", kind, extra);
1165
1259
  }
1166
1260
  function toNode(v, name) {
1167
- if (v instanceof import_core10.NodeImpl) return v;
1168
- return (0, import_core10.node)([], { initial: v, ...name ? { name } : void 0 });
1261
+ if (v instanceof import_core11.NodeImpl) return v;
1262
+ return (0, import_core11.node)([], { initial: v, ...name ? { name } : void 0 });
1169
1263
  }
1170
1264
  function ageSeconds(now, lastNs) {
1171
1265
  return (now - lastNs) / NS_PER_SEC;
@@ -1219,13 +1313,13 @@ function collection(name, opts = {}) {
1219
1313
  }
1220
1314
  const scoreFnDefault = () => ranked ? 1 : 0;
1221
1315
  const scoreInput = opts.score ?? scoreFnDefault;
1222
- const scoreNode = ranked && scoreInput instanceof import_core10.NodeImpl ? scoreInput : void 0;
1316
+ const scoreNode = ranked && scoreInput instanceof import_core11.NodeImpl ? scoreInput : void 0;
1223
1317
  const readScoreFn = () => {
1224
1318
  if (scoreNode) return scoreNode.cache ?? scoreFnDefault;
1225
1319
  return scoreInput;
1226
1320
  };
1227
1321
  const graph = new import_graph3.Graph(name);
1228
- const retentionScore = (_k, v) => ranked ? decay(v.baseScore, ageSeconds((0, import_core10.monotonicNs)(), v.lastAccessNs), decayRate, minScore) : v.lastAccessNs;
1322
+ const retentionScore = (_k, v) => ranked ? decay(v.baseScore, ageSeconds((0, import_core11.monotonicNs)(), v.lastAccessNs), decayRate, minScore) : v.lastAccessNs;
1229
1323
  const items = (0, import_extra8.reactiveMap)({
1230
1324
  name: "items",
1231
1325
  ...maxSize !== void 0 ? { retention: { score: retentionScore, maxSize } } : {}
@@ -1235,15 +1329,15 @@ function collection(name, opts = {}) {
1235
1329
  if (ranked && decayRate > 0) {
1236
1330
  const intervalMs = opts.refreshIntervalMs ?? Math.max(1, 1e3 * Math.LN2 / (10 * decayRate));
1237
1331
  const tickCounter = (0, import_extra8.fromTimer)(intervalMs, { period: intervalMs });
1238
- refreshTick = (0, import_core10.node)(
1332
+ refreshTick = (0, import_core11.node)(
1239
1333
  [tickCounter],
1240
1334
  (_batchData, actions) => {
1241
- actions.emit((0, import_core10.monotonicNs)());
1335
+ actions.emit((0, import_core11.monotonicNs)());
1242
1336
  },
1243
1337
  {
1244
1338
  name: "refresh_tick_ns",
1245
1339
  describeKind: "derived",
1246
- initial: (0, import_core10.monotonicNs)(),
1340
+ initial: (0, import_core11.monotonicNs)(),
1247
1341
  meta: memoryMeta("clock")
1248
1342
  }
1249
1343
  );
@@ -1254,7 +1348,7 @@ function collection(name, opts = {}) {
1254
1348
  const rankedDeps = [items.entries];
1255
1349
  if (refreshTick) rankedDeps.push(refreshTick);
1256
1350
  if (scoreNode) rankedDeps.push(scoreNode);
1257
- rankedNode = (0, import_core10.node)(
1351
+ rankedNode = (0, import_core11.node)(
1258
1352
  rankedDeps,
1259
1353
  (batchData, actions, ctx) => {
1260
1354
  const values = batchData.map(
@@ -1264,9 +1358,9 @@ function collection(name, opts = {}) {
1264
1358
  let now;
1265
1359
  if (refreshTick) {
1266
1360
  const tickValue = values[1];
1267
- now = typeof tickValue === "number" ? tickValue : (0, import_core10.monotonicNs)();
1361
+ now = typeof tickValue === "number" ? tickValue : (0, import_core11.monotonicNs)();
1268
1362
  } else {
1269
- now = (0, import_core10.monotonicNs)();
1363
+ now = (0, import_core11.monotonicNs)();
1270
1364
  }
1271
1365
  if (!snapshot || snapshot.size === 0) {
1272
1366
  actions.emit([]);
@@ -1291,7 +1385,7 @@ function collection(name, opts = {}) {
1291
1385
  );
1292
1386
  graph.add(rankedNode, { name: "ranked" });
1293
1387
  } else {
1294
- rankedNode = (0, import_core10.node)([], {
1388
+ rankedNode = (0, import_core11.node)([], {
1295
1389
  initial: [],
1296
1390
  name: "ranked",
1297
1391
  describeKind: "state",
@@ -1299,7 +1393,7 @@ function collection(name, opts = {}) {
1299
1393
  });
1300
1394
  graph.add(rankedNode, { name: "ranked" });
1301
1395
  }
1302
- const size = (0, import_core10.node)(
1396
+ const size = (0, import_core11.node)(
1303
1397
  [items.entries],
1304
1398
  (batchData, actions, ctx) => {
1305
1399
  const data = batchData.map(
@@ -1324,7 +1418,7 @@ function collection(name, opts = {}) {
1324
1418
  });
1325
1419
  const seqCursor = registerCursor(graph, "seq", 0);
1326
1420
  const upsertImpl = (id, value, _opts) => {
1327
- const now = (0, import_core10.monotonicNs)();
1421
+ const now = (0, import_core11.monotonicNs)();
1328
1422
  const prev = items.get(id);
1329
1423
  const baseScore = _opts?.score ?? readScoreFn()(value);
1330
1424
  items.set(id, {
@@ -1380,7 +1474,7 @@ function collection(name, opts = {}) {
1380
1474
  });
1381
1475
  function itemNode(id) {
1382
1476
  const idN = toNode(id, "id");
1383
- return (0, import_core10.node)(
1477
+ return (0, import_core11.node)(
1384
1478
  [items.entries, idN],
1385
1479
  (batchData, actions, ctx) => {
1386
1480
  const data = batchData.map(
@@ -1398,7 +1492,7 @@ function collection(name, opts = {}) {
1398
1492
  }
1399
1493
  function hasNode(id) {
1400
1494
  const idN = toNode(id, "id");
1401
- return (0, import_core10.node)(
1495
+ return (0, import_core11.node)(
1402
1496
  [items.entries, idN],
1403
1497
  (batchData, actions, ctx) => {
1404
1498
  const data = batchData.map(
@@ -1485,7 +1579,7 @@ function vectorIndex(opts = {}) {
1485
1579
  events.append({
1486
1580
  action: "evict",
1487
1581
  id: key,
1488
- t_ns: (0, import_core10.wallClockNs)(),
1582
+ t_ns: (0, import_core11.wallClockNs)(),
1489
1583
  seq: bumpCursor(seqCursor)
1490
1584
  });
1491
1585
  }
@@ -1510,7 +1604,7 @@ function vectorIndex(opts = {}) {
1510
1604
  id,
1511
1605
  vector: [...vector],
1512
1606
  ...copiedMeta !== void 0 ? { meta: copiedMeta } : {},
1513
- upsertedAtNs: (0, import_core10.monotonicNs)()
1607
+ upsertedAtNs: (0, import_core11.monotonicNs)()
1514
1608
  };
1515
1609
  entries.set(id, record);
1516
1610
  };
@@ -1566,7 +1660,7 @@ function vectorIndex(opts = {}) {
1566
1660
  });
1567
1661
  function searchNode(query, k = 5) {
1568
1662
  const kN = toNode(k, "k");
1569
- return (0, import_core10.node)(
1663
+ return (0, import_core11.node)(
1570
1664
  [entries.entries, query, kN],
1571
1665
  (batchData, actions, ctx) => {
1572
1666
  const values = batchData.map(
@@ -1682,7 +1776,7 @@ function knowledgeGraph(name, opts = {}) {
1682
1776
  });
1683
1777
  graph.add(entitiesMap.entries, { name: "entities" });
1684
1778
  graph.add(edgesMap.entries, { name: "edges" });
1685
- const adjacencyOut = (0, import_core10.node)(
1779
+ const adjacencyOut = (0, import_core11.node)(
1686
1780
  [edgesMap.entries],
1687
1781
  (batchData, actions, ctx) => {
1688
1782
  const data = batchData.map(
@@ -1699,7 +1793,7 @@ function knowledgeGraph(name, opts = {}) {
1699
1793
  meta: memoryMeta("adjacency_out")
1700
1794
  }
1701
1795
  );
1702
- const adjacencyIn = (0, import_core10.node)(
1796
+ const adjacencyIn = (0, import_core11.node)(
1703
1797
  [edgesMap.entries],
1704
1798
  (batchData, actions, ctx) => {
1705
1799
  const data = batchData.map(
@@ -1720,7 +1814,7 @@ function knowledgeGraph(name, opts = {}) {
1720
1814
  graph.add(adjacencyIn, { name: "adjacencyIn" });
1721
1815
  graph.addDisposer((0, import_extra8.keepalive)(adjacencyOut));
1722
1816
  graph.addDisposer((0, import_extra8.keepalive)(adjacencyIn));
1723
- const entityCount = (0, import_core10.node)(
1817
+ const entityCount = (0, import_core11.node)(
1724
1818
  [entitiesMap.entries],
1725
1819
  (batchData, actions, ctx) => {
1726
1820
  const data = batchData.map(
@@ -1731,7 +1825,7 @@ function knowledgeGraph(name, opts = {}) {
1731
1825
  },
1732
1826
  { name: "entityCount", describeKind: "derived", initial: 0, meta: memoryMeta("entity_count") }
1733
1827
  );
1734
- const edgeCount = (0, import_core10.node)(
1828
+ const edgeCount = (0, import_core11.node)(
1735
1829
  [edgesMap.entries],
1736
1830
  (batchData, actions, ctx) => {
1737
1831
  const data = batchData.map(
@@ -1768,7 +1862,7 @@ function knowledgeGraph(name, opts = {}) {
1768
1862
  events.append({
1769
1863
  action: "orphanRemove",
1770
1864
  id: candidate,
1771
- t_ns: (0, import_core10.wallClockNs)(),
1865
+ t_ns: (0, import_core11.wallClockNs)(),
1772
1866
  seq: bumpCursor(seqCursor)
1773
1867
  });
1774
1868
  }
@@ -1863,7 +1957,7 @@ function knowledgeGraph(name, opts = {}) {
1863
1957
  const idN = toNode(id, "id");
1864
1958
  const relN = relation !== void 0 ? toNode(relation, "relation") : void 0;
1865
1959
  const deps = relN ? [adjacencyOut, adjacencyIn, idN, relN] : [adjacencyOut, adjacencyIn, idN];
1866
- return (0, import_core10.node)(
1960
+ return (0, import_core11.node)(
1867
1961
  deps,
1868
1962
  (batchData, actions, ctx) => {
1869
1963
  const values = batchData.map(