@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.
- package/dist/base/composition/index.cjs +4 -3
- package/dist/base/composition/index.cjs.map +1 -1
- package/dist/base/composition/index.d.cts +14 -5
- package/dist/base/composition/index.d.ts +14 -5
- package/dist/base/composition/index.js +8 -8
- package/dist/base/index.cjs +152 -78
- package/dist/base/index.cjs.map +1 -1
- package/dist/base/index.d.cts +2 -2
- package/dist/base/index.d.ts +2 -2
- package/dist/base/index.js +75 -70
- package/dist/base/io/index.cjs +31 -17
- package/dist/base/io/index.cjs.map +1 -1
- package/dist/base/io/index.d.cts +32 -5
- package/dist/base/io/index.d.ts +32 -5
- package/dist/base/io/index.js +1 -1
- package/dist/base/mutation/index.cjs +21 -0
- package/dist/base/mutation/index.cjs.map +1 -1
- package/dist/base/mutation/index.d.cts +23 -1
- package/dist/base/mutation/index.d.ts +23 -1
- package/dist/base/mutation/index.js +3 -1
- package/dist/base/sources/browser/index.cjs +5 -3
- package/dist/base/sources/browser/index.cjs.map +1 -1
- package/dist/base/sources/browser/index.d.cts +20 -2
- package/dist/base/sources/browser/index.d.ts +20 -2
- package/dist/base/sources/browser/index.js +5 -3
- package/dist/base/sources/browser/index.js.map +1 -1
- package/dist/base/sources/event/index.cjs +28 -0
- package/dist/base/sources/event/index.cjs.map +1 -1
- package/dist/base/sources/event/index.d.cts +67 -3
- package/dist/base/sources/event/index.d.ts +67 -3
- package/dist/base/sources/event/index.js +4 -1
- package/dist/base/sources/index.cjs +75 -37
- package/dist/base/sources/index.cjs.map +1 -1
- package/dist/base/sources/index.d.cts +1 -1
- package/dist/base/sources/index.d.ts +1 -1
- package/dist/base/sources/index.js +5 -2
- package/dist/{chunk-R6ZCSXKX.js → chunk-23MAWVOJ.js} +3 -3
- package/dist/{chunk-MS3WPRJR.js → chunk-3REMCHSS.js} +6 -6
- package/dist/chunk-3REMCHSS.js.map +1 -0
- package/dist/{chunk-CEVNQ74M.js → chunk-3YGXPUHW.js} +2 -2
- package/dist/{chunk-CEVNQ74M.js.map → chunk-3YGXPUHW.js.map} +1 -1
- package/dist/{chunk-6ZLCPUXS.js → chunk-46X2EFQH.js} +15 -4
- package/dist/chunk-46X2EFQH.js.map +1 -0
- package/dist/{chunk-NY2PYHNC.js → chunk-5UY3PNFY.js} +12 -5
- package/dist/chunk-5UY3PNFY.js.map +1 -0
- package/dist/{chunk-FQSQONOU.js → chunk-65OM4XLQ.js} +49 -3
- package/dist/chunk-65OM4XLQ.js.map +1 -0
- package/dist/{chunk-3PSLNJDU.js → chunk-6DQYBIHW.js} +314 -49
- package/dist/chunk-6DQYBIHW.js.map +1 -0
- package/dist/{chunk-LDCSZ72P.js → chunk-6YBER5UP.js} +3 -3
- package/dist/{chunk-LDCSZ72P.js.map → chunk-6YBER5UP.js.map} +1 -1
- package/dist/{chunk-3O3NKZJW.js → chunk-7T7WLEPM.js} +24 -3
- package/dist/chunk-7T7WLEPM.js.map +1 -0
- package/dist/{chunk-PKPO3JTZ.js → chunk-AQAKDE7F.js} +29 -11
- package/dist/chunk-AQAKDE7F.js.map +1 -0
- package/dist/{chunk-6MRSX3YK.js → chunk-B5Y5GPD5.js} +2 -2
- package/dist/{chunk-BXGZFGZ4.js → chunk-C5QD5DQX.js} +22 -1
- package/dist/chunk-C5QD5DQX.js.map +1 -0
- package/dist/{chunk-4XCHZRUJ.js → chunk-D5YGR4TP.js} +58 -7
- package/dist/chunk-D5YGR4TP.js.map +1 -0
- package/dist/{chunk-NPRP3MCV.js → chunk-DHDCOOJU.js} +2 -2
- package/dist/chunk-DHDCOOJU.js.map +1 -0
- package/dist/{chunk-VP3TIUDF.js → chunk-DVTDF5OI.js} +2 -2
- package/dist/{chunk-OXD5LFQP.js → chunk-G7H6PN7P.js} +2 -2
- package/dist/{chunk-EL5VHUGK.js → chunk-GGKHHG5Y.js} +32 -18
- package/dist/chunk-GGKHHG5Y.js.map +1 -0
- package/dist/{chunk-446I4EGD.js → chunk-J5TBZFBD.js} +2 -2
- package/dist/{chunk-7AVQIGF6.js → chunk-K4ZYJ4EM.js} +554 -460
- package/dist/chunk-K4ZYJ4EM.js.map +1 -0
- package/dist/{chunk-QFE5BQH7.js → chunk-LTSI7ULC.js} +2 -2
- package/dist/{chunk-5GVURVIG.js → chunk-MMHGYX44.js} +12 -2
- package/dist/{chunk-5GVURVIG.js.map → chunk-MMHGYX44.js.map} +1 -1
- package/dist/{chunk-KRFGO5QH.js → chunk-MQMTRKY3.js} +118 -43
- package/dist/chunk-MQMTRKY3.js.map +1 -0
- package/dist/{chunk-42FQ27MQ.js → chunk-MTODGQBR.js} +44 -179
- package/dist/chunk-MTODGQBR.js.map +1 -0
- package/dist/{chunk-FVINAAKA.js → chunk-NBK6QQMG.js} +14 -13
- package/dist/{chunk-FVINAAKA.js.map → chunk-NBK6QQMG.js.map} +1 -1
- package/dist/{chunk-KNU73RZW.js → chunk-NSA5K5G2.js} +2 -2
- package/dist/{chunk-MLTPJMH6.js → chunk-QQYULEZL.js} +2 -2
- package/dist/chunk-QSW4DFKE.js +31 -0
- package/dist/chunk-QSW4DFKE.js.map +1 -0
- package/dist/{chunk-VAZXUK6G.js → chunk-SUNCHMML.js} +2 -2
- package/dist/{chunk-EP4WVQLX.js → chunk-T2U6N3FV.js} +6 -6
- package/dist/{chunk-T7SP3EYR.js → chunk-T5URUIIY.js} +33 -24
- package/dist/chunk-T5URUIIY.js.map +1 -0
- package/dist/{chunk-VNXAF2KE.js → chunk-TPTZZV25.js} +6 -6
- package/dist/chunk-TPTZZV25.js.map +1 -0
- package/dist/{chunk-IOJDYUA7.js → chunk-V46JWFGV.js} +6 -5
- package/dist/chunk-V46JWFGV.js.map +1 -0
- package/dist/{chunk-WGDEBIP4.js → chunk-X6ESZDR6.js} +5 -6
- package/dist/chunk-X6ESZDR6.js.map +1 -0
- package/dist/{chunk-N65E26UL.js → chunk-XEWV254I.js} +2 -2
- package/dist/{chunk-N65E26UL.js.map → chunk-XEWV254I.js.map} +1 -1
- package/dist/{chunk-PTWADEH3.js → chunk-YBJVKMTM.js} +34 -14
- package/dist/chunk-YBJVKMTM.js.map +1 -0
- package/dist/{chunk-DDTS7F5O.js → chunk-ZW32BPXV.js} +12 -3
- package/dist/chunk-ZW32BPXV.js.map +1 -0
- package/dist/compat/index.cjs +51 -4
- package/dist/compat/index.cjs.map +1 -1
- package/dist/compat/index.d.cts +1 -1
- package/dist/compat/index.d.ts +1 -1
- package/dist/compat/index.js +6 -6
- package/dist/compat/nestjs/index.cjs +51 -4
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +1 -1
- package/dist/compat/nestjs/index.d.ts +1 -1
- package/dist/compat/nestjs/index.js +3 -3
- package/dist/{fallback-Bx46zqky.d.cts → fallback-BROR6ZhO.d.cts} +1 -1
- package/dist/{fallback-pIWW8A2d.d.ts → fallback-DO80aM_3.d.ts} +1 -1
- package/dist/{index-B_p8tnvf.d.cts → index-D1z3XcF9.d.cts} +1 -0
- package/dist/{index-_HDSmPyp.d.ts → index-DZ6yua0Q.d.ts} +1 -0
- package/dist/index.cjs +2215 -1676
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +169 -146
- package/dist/index.js.map +1 -1
- package/dist/presets/ai/index.cjs +46 -0
- package/dist/presets/ai/index.cjs.map +1 -1
- package/dist/presets/ai/index.js +12 -12
- package/dist/presets/harness/index.cjs +130 -18
- package/dist/presets/harness/index.cjs.map +1 -1
- package/dist/presets/harness/index.d.cts +15 -5
- package/dist/presets/harness/index.d.ts +15 -5
- package/dist/presets/harness/index.js +22 -22
- package/dist/presets/index.cjs +222 -53
- package/dist/presets/index.cjs.map +1 -1
- package/dist/presets/index.d.cts +2 -2
- package/dist/presets/index.d.ts +2 -2
- package/dist/presets/index.js +45 -45
- package/dist/presets/inspect/index.cjs +63 -14
- package/dist/presets/inspect/index.cjs.map +1 -1
- package/dist/presets/inspect/index.d.cts +1 -1
- package/dist/presets/inspect/index.d.ts +1 -1
- package/dist/presets/inspect/index.js +6 -6
- package/dist/presets/resilience/index.cjs +29 -21
- package/dist/presets/resilience/index.cjs.map +1 -1
- package/dist/presets/resilience/index.d.cts +12 -8
- package/dist/presets/resilience/index.d.ts +12 -8
- package/dist/presets/resilience/index.js +3 -3
- package/dist/{rate-limiter-DpVbSYdH.d.cts → rate-limiter-DC26FM8J.d.cts} +10 -1
- package/dist/{rate-limiter-CEALq4N1.d.ts → rate-limiter-DyWpwpQP.d.ts} +10 -1
- package/dist/{reactive-layout-fswlBUvX.d.ts → reactive-layout-BBBWH0V_.d.cts} +85 -4
- package/dist/{reactive-layout-fswlBUvX.d.cts → reactive-layout-BBBWH0V_.d.ts} +85 -4
- package/dist/solutions/index.cjs +168 -47
- package/dist/solutions/index.cjs.map +1 -1
- package/dist/solutions/index.d.cts +2 -2
- package/dist/solutions/index.d.ts +2 -2
- package/dist/solutions/index.js +28 -28
- package/dist/{spawnable-5mDY501F.d.cts → spawnable-B2IlW60f.d.cts} +23 -2
- package/dist/{spawnable-D3lR0oQu.d.ts → spawnable-tttFz2Nh.d.ts} +23 -2
- package/dist/testing/index.cjs +94 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +59 -0
- package/dist/testing/index.d.ts +59 -0
- package/dist/testing/index.js +73 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/utils/ai/browser.cjs.map +1 -1
- package/dist/utils/ai/browser.d.cts +2 -2
- package/dist/utils/ai/browser.d.ts +2 -2
- package/dist/utils/ai/browser.js +6 -6
- package/dist/utils/ai/browser.js.map +1 -1
- package/dist/utils/ai/index.cjs +250 -166
- package/dist/utils/ai/index.cjs.map +1 -1
- package/dist/utils/ai/index.d.cts +108 -12
- package/dist/utils/ai/index.d.ts +108 -12
- package/dist/utils/ai/index.js +21 -19
- package/dist/utils/ai/node.cjs.map +1 -1
- package/dist/utils/ai/node.d.cts +5 -5
- package/dist/utils/ai/node.d.ts +5 -5
- package/dist/utils/ai/node.js +2 -2
- package/dist/utils/ai/node.js.map +1 -1
- package/dist/utils/cqrs/index.cjs +29 -3
- package/dist/utils/cqrs/index.cjs.map +1 -1
- package/dist/utils/cqrs/index.d.cts +12 -7
- package/dist/utils/cqrs/index.d.ts +12 -7
- package/dist/utils/cqrs/index.js +2 -2
- package/dist/utils/demo-shell/index.cjs +45 -19
- package/dist/utils/demo-shell/index.cjs.map +1 -1
- package/dist/utils/demo-shell/index.d.cts +1 -1
- package/dist/utils/demo-shell/index.d.ts +1 -1
- package/dist/utils/demo-shell/index.js +2 -2
- package/dist/utils/domain-templates/index.cjs.map +1 -1
- package/dist/utils/domain-templates/index.js +3 -3
- package/dist/utils/graphspec/index.cjs.map +1 -1
- package/dist/utils/graphspec/index.js +3 -3
- package/dist/utils/index.cjs +1642 -1225
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +7 -7
- package/dist/utils/index.d.ts +7 -7
- package/dist/utils/index.js +72 -54
- package/dist/utils/inspect/index.cjs +52 -4
- package/dist/utils/inspect/index.cjs.map +1 -1
- package/dist/utils/inspect/index.d.cts +32 -3
- package/dist/utils/inspect/index.d.ts +32 -3
- package/dist/utils/inspect/index.js +4 -4
- package/dist/utils/job-queue/index.cjs +46 -9
- package/dist/utils/job-queue/index.cjs.map +1 -1
- package/dist/utils/job-queue/index.d.cts +33 -3
- package/dist/utils/job-queue/index.d.ts +33 -3
- package/dist/utils/job-queue/index.js +2 -2
- package/dist/utils/memory/index.cjs +556 -462
- package/dist/utils/memory/index.cjs.map +1 -1
- package/dist/utils/memory/index.d.cts +203 -24
- package/dist/utils/memory/index.d.ts +203 -24
- package/dist/utils/memory/index.js +10 -2
- package/dist/utils/messaging/index.cjs.map +1 -1
- package/dist/utils/messaging/index.d.cts +4 -3
- package/dist/utils/messaging/index.d.ts +4 -3
- package/dist/utils/messaging/index.js +2 -2
- package/dist/utils/orchestration/index.cjs +9 -0
- package/dist/utils/orchestration/index.cjs.map +1 -1
- package/dist/utils/orchestration/index.js +3 -3
- package/dist/utils/process/index.cjs +32 -2
- package/dist/utils/process/index.cjs.map +1 -1
- package/dist/utils/process/index.d.cts +4 -3
- package/dist/utils/process/index.d.ts +4 -3
- package/dist/utils/process/index.js +2 -2
- package/dist/utils/reactive-layout/index.cjs +184 -55
- package/dist/utils/reactive-layout/index.cjs.map +1 -1
- package/dist/utils/reactive-layout/index.d.cts +128 -3
- package/dist/utils/reactive-layout/index.d.ts +128 -3
- package/dist/utils/reactive-layout/index.js +16 -8
- package/dist/utils/reduction/index.cjs.map +1 -1
- package/dist/utils/reduction/index.js +2 -2
- package/dist/utils/resilience/index.cjs +29 -20
- package/dist/utils/resilience/index.cjs.map +1 -1
- package/dist/utils/resilience/index.d.cts +1 -1
- package/dist/utils/resilience/index.d.ts +1 -1
- package/dist/utils/resilience/index.js +2 -2
- package/dist/utils/surface/index.cjs.map +1 -1
- package/dist/utils/surface/index.js +4 -4
- package/package.json +15 -3
- package/dist/chunk-3O3NKZJW.js.map +0 -1
- package/dist/chunk-3PSLNJDU.js.map +0 -1
- package/dist/chunk-42FQ27MQ.js.map +0 -1
- package/dist/chunk-4XCHZRUJ.js.map +0 -1
- package/dist/chunk-6ZLCPUXS.js.map +0 -1
- package/dist/chunk-7AVQIGF6.js.map +0 -1
- package/dist/chunk-BXGZFGZ4.js.map +0 -1
- package/dist/chunk-DDTS7F5O.js.map +0 -1
- package/dist/chunk-EL5VHUGK.js.map +0 -1
- package/dist/chunk-FQSQONOU.js.map +0 -1
- package/dist/chunk-IOJDYUA7.js.map +0 -1
- package/dist/chunk-KRFGO5QH.js.map +0 -1
- package/dist/chunk-MS3WPRJR.js.map +0 -1
- package/dist/chunk-NPRP3MCV.js.map +0 -1
- package/dist/chunk-NY2PYHNC.js.map +0 -1
- package/dist/chunk-PKPO3JTZ.js.map +0 -1
- package/dist/chunk-PTWADEH3.js.map +0 -1
- package/dist/chunk-T7SP3EYR.js.map +0 -1
- package/dist/chunk-VNXAF2KE.js.map +0 -1
- package/dist/chunk-W2BOPXTI.js +0 -1
- package/dist/chunk-W2BOPXTI.js.map +0 -1
- package/dist/chunk-WGDEBIP4.js.map +0 -1
- /package/dist/{chunk-R6ZCSXKX.js.map → chunk-23MAWVOJ.js.map} +0 -0
- /package/dist/{chunk-6MRSX3YK.js.map → chunk-B5Y5GPD5.js.map} +0 -0
- /package/dist/{chunk-VP3TIUDF.js.map → chunk-DVTDF5OI.js.map} +0 -0
- /package/dist/{chunk-OXD5LFQP.js.map → chunk-G7H6PN7P.js.map} +0 -0
- /package/dist/{chunk-446I4EGD.js.map → chunk-J5TBZFBD.js.map} +0 -0
- /package/dist/{chunk-QFE5BQH7.js.map → chunk-LTSI7ULC.js.map} +0 -0
- /package/dist/{chunk-KNU73RZW.js.map → chunk-NSA5K5G2.js.map} +0 -0
- /package/dist/{chunk-MLTPJMH6.js.map → chunk-QQYULEZL.js.map} +0 -0
- /package/dist/{chunk-VAZXUK6G.js.map → chunk-SUNCHMML.js.map} +0 -0
- /package/dist/{chunk-EP4WVQLX.js.map → chunk-T2U6N3FV.js.map} +0 -0
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
createAuditLog,
|
|
10
10
|
mutate,
|
|
11
11
|
registerCursor
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-C5QD5DQX.js";
|
|
13
13
|
|
|
14
14
|
// src/utils/memory/index.ts
|
|
15
|
-
import { monotonicNs as
|
|
15
|
+
import { monotonicNs as monotonicNs3, NodeImpl, node as node10, wallClockNs as wallClockNs3 } from "@graphrefly/pure-ts/core";
|
|
16
16
|
import { fromTimer as fromTimer3, keepalive as keepalive6, reactiveMap } from "@graphrefly/pure-ts/extra";
|
|
17
17
|
import { Graph as Graph2 } from "@graphrefly/pure-ts/graph";
|
|
18
18
|
|
|
@@ -51,479 +51,534 @@ function currentlyValid(f, asOf) {
|
|
|
51
51
|
function lastOf(batch, prev) {
|
|
52
52
|
return batch != null && batch.length > 0 ? batch.at(-1) : prev;
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
54
|
+
var ReactiveFactStoreGraph = class extends Graph {
|
|
55
|
+
// ④ Topic outputs (caller subscribes for custom processing).
|
|
56
|
+
/** Per-shard `state<FactStore<T>>` nodes (length = shard count). */
|
|
57
|
+
shards;
|
|
58
|
+
/** Unified read view across all shards (derived). */
|
|
59
|
+
factStore;
|
|
60
|
+
dependentsIndex;
|
|
61
|
+
answer;
|
|
62
|
+
cascade;
|
|
63
|
+
cascadeOverflow;
|
|
64
|
+
review;
|
|
65
|
+
consolidated;
|
|
66
|
+
events;
|
|
67
|
+
/**
|
|
68
|
+
* Payload-carrying, replayable log of every committed fragment. Present iff
|
|
69
|
+
* {@link ReactiveFactStoreConfig.recordIngest} is `true`. Unlike
|
|
70
|
+
* {@link ReactiveFactStoreGraph.events} (action-only audit), each entry is
|
|
71
|
+
* the full {@link MemoryFragment} — `attachStorage` it for a durable,
|
|
72
|
+
* replayable projection source (see `recordIngest` docs for the recipe).
|
|
73
|
+
*/
|
|
74
|
+
ingestLog;
|
|
75
|
+
constructor(config) {
|
|
76
|
+
const shardCount = Math.max(1, config.shardCount ?? 4);
|
|
77
|
+
const maxIterations = Math.max(1, config.cascadeMaxIterations ?? 8);
|
|
78
|
+
const reviewThreshold = config.reviewThreshold ?? 0.3;
|
|
79
|
+
const shardBy = config.shardBy ?? ((f) => fnv1a(String(f.id)) % shardCount);
|
|
80
|
+
let cascadeIteration = 0;
|
|
81
|
+
const processedRoots = /* @__PURE__ */ new Set();
|
|
82
|
+
super("reactive_fact_store");
|
|
83
|
+
const events = createAuditLog({
|
|
84
|
+
name: "events",
|
|
85
|
+
retainedLimit: 1024,
|
|
86
|
+
graph: this
|
|
78
87
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const key = shardBy(f);
|
|
85
|
-
const n = typeof key === "number" ? key : fnv1a(String(key));
|
|
86
|
-
const idx = (n % shardCount + shardCount) % shardCount;
|
|
87
|
-
return idx;
|
|
88
|
-
};
|
|
89
|
-
const findShardOf = (id) => {
|
|
88
|
+
const seqCursor = registerCursor(this, "seq", 0);
|
|
89
|
+
const ingestLog = config.recordIngest ? reactiveLog([], { name: "ingest_log" }) : void 0;
|
|
90
|
+
if (ingestLog) this.addDisposer(() => ingestLog.dispose());
|
|
91
|
+
const emptyStore = () => ({ byId: /* @__PURE__ */ new Map() });
|
|
92
|
+
const shards = [];
|
|
90
93
|
for (let s = 0; s < shardCount; s += 1) {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (!fs) continue;
|
|
101
|
-
for (const [k, v] of fs.byId) out2.set(k, v);
|
|
102
|
-
}
|
|
103
|
-
return out2;
|
|
104
|
-
};
|
|
105
|
-
const commitFragment = (f) => {
|
|
106
|
-
const idx = shardIndexFor(f);
|
|
107
|
-
const cur = shards[idx].cache ?? emptyStore();
|
|
108
|
-
const next = new Map(cur.byId);
|
|
109
|
-
next.set(f.id, f);
|
|
110
|
-
shards[idx].emit({ byId: next });
|
|
111
|
-
};
|
|
112
|
-
const replaceFragment = (id, mut) => {
|
|
113
|
-
const idx = findShardOf(id);
|
|
114
|
-
if (idx < 0) return false;
|
|
115
|
-
const cur = shards[idx].cache;
|
|
116
|
-
const prev = cur.byId.get(id);
|
|
117
|
-
if (!prev) return false;
|
|
118
|
-
const next = new Map(cur.byId);
|
|
119
|
-
next.set(id, mut(prev));
|
|
120
|
-
shards[idx].emit({ byId: next });
|
|
121
|
-
return true;
|
|
122
|
-
};
|
|
123
|
-
const dependentsIndex = node([], {
|
|
124
|
-
initial: /* @__PURE__ */ new Map(),
|
|
125
|
-
name: "dependents_index",
|
|
126
|
-
describeKind: "state",
|
|
127
|
-
meta: factMeta("factstore", { role: "dependents_index" })
|
|
128
|
-
});
|
|
129
|
-
graph.add(dependentsIndex, { name: "dependents_index" });
|
|
130
|
-
graph.addDisposer(keepalive(dependentsIndex));
|
|
131
|
-
const indexFragment = (f, deps) => {
|
|
132
|
-
const cur = dependentsIndex.cache;
|
|
133
|
-
const next = /* @__PURE__ */ new Map();
|
|
134
|
-
for (const [k, v] of cur) next.set(k, [...v]);
|
|
135
|
-
for (const src of deps) {
|
|
136
|
-
const bucket = next.get(src) ?? [];
|
|
137
|
-
if (!bucket.includes(f.id)) bucket.push(f.id);
|
|
138
|
-
next.set(src, bucket);
|
|
94
|
+
const shard = node([], {
|
|
95
|
+
initial: emptyStore(),
|
|
96
|
+
name: `shard_${s}`,
|
|
97
|
+
describeKind: "state",
|
|
98
|
+
meta: factMeta("factstore", { shard: s })
|
|
99
|
+
});
|
|
100
|
+
this.add(shard, { name: `shard_${s}` });
|
|
101
|
+
this.addDisposer(keepalive(shard));
|
|
102
|
+
shards.push(shard);
|
|
139
103
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
name: "fact_store",
|
|
151
|
-
describeKind: "derived",
|
|
152
|
-
initial: emptyStore(),
|
|
153
|
-
meta: factMeta("factstore", { role: "read_view" }),
|
|
154
|
-
// F10a: `allFacts()` builds a fresh Map every detector retrigger.
|
|
155
|
-
// Fragments are immutable (replaced wholesale on mutation), so a
|
|
156
|
-
// same-size + per-key-identity check is a sound structural equality
|
|
157
|
-
// that stops `factStore` (and its `review` dependent) from re-firing
|
|
158
|
-
// every cascade wave when nothing actually changed.
|
|
159
|
-
equals: (a, b) => {
|
|
160
|
-
if (a === b) return true;
|
|
161
|
-
if (a.byId.size !== b.byId.size) return false;
|
|
162
|
-
for (const [k, v] of a.byId) {
|
|
163
|
-
if (b.byId.get(k) !== v) return false;
|
|
164
|
-
}
|
|
165
|
-
return true;
|
|
104
|
+
const shardIndexFor = (f) => {
|
|
105
|
+
const key = shardBy(f);
|
|
106
|
+
const n = typeof key === "number" ? key : fnv1a(String(key));
|
|
107
|
+
const idx = (n % shardCount + shardCount) % shardCount;
|
|
108
|
+
return idx;
|
|
109
|
+
};
|
|
110
|
+
const findShardOf = (id) => {
|
|
111
|
+
for (let s = 0; s < shardCount; s += 1) {
|
|
112
|
+
const fs = shards[s].cache;
|
|
113
|
+
if (fs?.byId.has(id)) return s;
|
|
166
114
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (f == null) {
|
|
176
|
-
actions.emit(null);
|
|
177
|
-
return;
|
|
115
|
+
return -1;
|
|
116
|
+
};
|
|
117
|
+
const allFacts = () => {
|
|
118
|
+
const out = /* @__PURE__ */ new Map();
|
|
119
|
+
for (const sh of shards) {
|
|
120
|
+
const fs = sh.cache;
|
|
121
|
+
if (!fs) continue;
|
|
122
|
+
for (const [k, v] of fs.byId) out.set(k, v);
|
|
178
123
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
124
|
+
return out;
|
|
125
|
+
};
|
|
126
|
+
const commitFragment = (f) => {
|
|
127
|
+
const idx = shardIndexFor(f);
|
|
128
|
+
const cur = shards[idx].cache ?? emptyStore();
|
|
129
|
+
const next = new Map(cur.byId);
|
|
130
|
+
next.set(f.id, f);
|
|
131
|
+
shards[idx].emit({ byId: next });
|
|
132
|
+
};
|
|
133
|
+
const replaceFragment = (id, mut) => {
|
|
134
|
+
const idx = findShardOf(id);
|
|
135
|
+
if (idx < 0) return false;
|
|
136
|
+
const cur = shards[idx].cache;
|
|
137
|
+
const prev = cur.byId.get(id);
|
|
138
|
+
if (!prev) return false;
|
|
139
|
+
const next = new Map(cur.byId);
|
|
140
|
+
next.set(id, mut(prev));
|
|
141
|
+
shards[idx].emit({ byId: next });
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
144
|
+
const dependentsIndex = node([], {
|
|
145
|
+
initial: /* @__PURE__ */ new Map(),
|
|
146
|
+
name: "dependents_index",
|
|
147
|
+
describeKind: "state",
|
|
148
|
+
meta: factMeta("factstore", { role: "dependents_index" })
|
|
149
|
+
});
|
|
150
|
+
this.add(dependentsIndex, { name: "dependents_index" });
|
|
151
|
+
this.addDisposer(keepalive(dependentsIndex));
|
|
152
|
+
const indexFragment = (f, deps) => {
|
|
153
|
+
const cur = dependentsIndex.cache;
|
|
154
|
+
const next = /* @__PURE__ */ new Map();
|
|
155
|
+
for (const [k, v] of cur) next.set(k, [...v]);
|
|
156
|
+
for (const src of deps) {
|
|
157
|
+
const bucket = next.get(src) ?? [];
|
|
158
|
+
if (!bucket.includes(f.id)) bucket.push(f.id);
|
|
159
|
+
next.set(src, bucket);
|
|
160
|
+
}
|
|
161
|
+
dependentsIndex.emit(next);
|
|
162
|
+
};
|
|
163
|
+
const factStore = node(
|
|
164
|
+
shards,
|
|
165
|
+
(batchData, actions, ctx) => {
|
|
166
|
+
void batchData;
|
|
167
|
+
void ctx;
|
|
168
|
+
actions.emit({ byId: allFacts() });
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: "fact_store",
|
|
172
|
+
describeKind: "derived",
|
|
173
|
+
initial: emptyStore(),
|
|
174
|
+
meta: factMeta("factstore", { role: "read_view" }),
|
|
175
|
+
// F10a: `allFacts()` builds a fresh Map every detector retrigger.
|
|
176
|
+
// Fragments are immutable (replaced wholesale on mutation), so a
|
|
177
|
+
// same-size + per-key-identity check is a sound structural equality
|
|
178
|
+
// that stops `factStore` (and its `review` dependent) from re-firing
|
|
179
|
+
// every cascade wave when nothing actually changed.
|
|
180
|
+
equals: (a, b) => {
|
|
181
|
+
if (a === b) return true;
|
|
182
|
+
if (a.byId.size !== b.byId.size) return false;
|
|
183
|
+
for (const [k, v] of a.byId) {
|
|
184
|
+
if (b.byId.get(k) !== v) return false;
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
this.add(factStore, { name: "fact_store" });
|
|
191
|
+
this.addDisposer(keepalive(factStore));
|
|
192
|
+
const extractOp = node(
|
|
193
|
+
config.admissionFilter ? [config.ingest, config.admissionFilter] : [config.ingest],
|
|
194
|
+
(batchData, actions, ctx) => {
|
|
195
|
+
const f = lastOf(batchData[0], ctx.prevData[0]);
|
|
196
|
+
if (f == null) {
|
|
182
197
|
actions.emit(null);
|
|
183
198
|
return;
|
|
184
199
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
actions.emit(f);
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
name: "extract_op",
|
|
195
|
-
describeKind: "derived",
|
|
196
|
-
meta: factMeta("extract")
|
|
197
|
-
}
|
|
198
|
-
);
|
|
199
|
-
graph.add(extractOp, { name: "extract_op" });
|
|
200
|
-
graph.addDisposer(keepalive(extractOp));
|
|
201
|
-
const invalidationDetector = node(
|
|
202
|
-
[...shards],
|
|
203
|
-
(batchData, actions, ctx) => {
|
|
204
|
-
void batchData;
|
|
205
|
-
void ctx;
|
|
206
|
-
const facts = allFacts();
|
|
207
|
-
const index = dependentsIndex.cache;
|
|
208
|
-
const out2 = [];
|
|
209
|
-
const seen = /* @__PURE__ */ new Set();
|
|
210
|
-
for (const f of facts.values()) {
|
|
211
|
-
const obsolete = f.validTo !== void 0;
|
|
212
|
-
if (!obsolete) continue;
|
|
213
|
-
if (processedRoots.has(f.id)) continue;
|
|
214
|
-
const dependents = index.get(f.id) ?? [];
|
|
215
|
-
for (const dep of dependents) {
|
|
216
|
-
const depFact = facts.get(dep);
|
|
217
|
-
if (!depFact || depFact.validTo !== void 0) continue;
|
|
218
|
-
const k = `${f.id}->${dep}`;
|
|
219
|
-
if (seen.has(k)) continue;
|
|
220
|
-
seen.add(k);
|
|
221
|
-
out2.push({
|
|
222
|
-
factId: dep,
|
|
223
|
-
rootFactId: f.id,
|
|
224
|
-
reason: "obsolete",
|
|
225
|
-
// `obsolete` guard above guarantees `f.validTo` is set.
|
|
226
|
-
rootValidTo: f.validTo,
|
|
227
|
-
iteration: cascadeIteration + 1,
|
|
228
|
-
causalReason: `dependentsIndex[${f.id}] \u2192 ${dep} (obsolete: validTo set)`
|
|
229
|
-
});
|
|
200
|
+
if (config.admissionFilter) {
|
|
201
|
+
const filter = lastOf(batchData[1], ctx.prevData[1]);
|
|
202
|
+
if (filter && !filter(f)) {
|
|
203
|
+
actions.emit(null);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
230
206
|
}
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
if (out2.length === 0) {
|
|
207
|
+
const deps = config.extractDependencies(f);
|
|
234
208
|
cascadeIteration = 0;
|
|
209
|
+
processedRoots.delete(f.id);
|
|
210
|
+
commitFragment(f);
|
|
211
|
+
indexFragment(f, deps);
|
|
212
|
+
actions.emit(f);
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "extract_op",
|
|
216
|
+
describeKind: "derived",
|
|
217
|
+
meta: factMeta("extract")
|
|
235
218
|
}
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (cascadeIteration > maxIterations) {
|
|
282
|
-
const sample = [...byId.keys()].slice(0, OVERFLOW_SAMPLE_SIZE);
|
|
283
|
-
const rootFactId = evts[0]?.rootFactId ?? "";
|
|
284
|
-
cascadeOverflow.emit({
|
|
285
|
-
droppedCount: byId.size,
|
|
286
|
-
sample,
|
|
287
|
-
rootFactId
|
|
288
|
-
});
|
|
289
|
-
events.append({
|
|
290
|
-
action: "overflow",
|
|
291
|
-
reason: "cascade",
|
|
292
|
-
id: rootFactId,
|
|
293
|
-
t_ns: wallClockNs(),
|
|
294
|
-
seq: bumpCursor(seqCursor)
|
|
295
|
-
});
|
|
296
|
-
actions.emit([]);
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
for (const [id, e] of byId) {
|
|
300
|
-
replaceFragment(
|
|
301
|
-
id,
|
|
302
|
-
(prev) => prev.validTo !== void 0 ? prev : { ...prev, validTo: e.rootValidTo }
|
|
303
|
-
);
|
|
219
|
+
);
|
|
220
|
+
this.add(extractOp, { name: "extract_op" });
|
|
221
|
+
this.addDisposer(keepalive(extractOp));
|
|
222
|
+
const invalidationDetector = node(
|
|
223
|
+
[...shards],
|
|
224
|
+
(batchData, actions, ctx) => {
|
|
225
|
+
void batchData;
|
|
226
|
+
void ctx;
|
|
227
|
+
const facts = allFacts();
|
|
228
|
+
const index = dependentsIndex.cache;
|
|
229
|
+
const out = [];
|
|
230
|
+
const seen = /* @__PURE__ */ new Set();
|
|
231
|
+
for (const f of facts.values()) {
|
|
232
|
+
const obsolete = f.validTo !== void 0;
|
|
233
|
+
if (!obsolete) continue;
|
|
234
|
+
if (processedRoots.has(f.id)) continue;
|
|
235
|
+
const dependents = index.get(f.id) ?? [];
|
|
236
|
+
for (const dep of dependents) {
|
|
237
|
+
const depFact = facts.get(dep);
|
|
238
|
+
if (!depFact || depFact.validTo !== void 0) continue;
|
|
239
|
+
const k = `${f.id}->${dep}`;
|
|
240
|
+
if (seen.has(k)) continue;
|
|
241
|
+
seen.add(k);
|
|
242
|
+
out.push({
|
|
243
|
+
factId: dep,
|
|
244
|
+
rootFactId: f.id,
|
|
245
|
+
reason: "obsolete",
|
|
246
|
+
// `obsolete` guard above guarantees `f.validTo` is set.
|
|
247
|
+
rootValidTo: f.validTo,
|
|
248
|
+
iteration: cascadeIteration + 1,
|
|
249
|
+
causalReason: `dependentsIndex[${f.id}] \u2192 ${dep} (obsolete: validTo set)`
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
processedRoots.add(f.id);
|
|
253
|
+
}
|
|
254
|
+
if (out.length === 0) {
|
|
255
|
+
cascadeIteration = 0;
|
|
256
|
+
}
|
|
257
|
+
actions.emit(out);
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "invalidation_detector",
|
|
261
|
+
describeKind: "derived",
|
|
262
|
+
initial: [],
|
|
263
|
+
meta: factMeta("invalidation", { cycle: "cascade" })
|
|
304
264
|
}
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const fs = lastOf(batchData[0], ctx.prevData[0]);
|
|
320
|
-
if (fs == null) {
|
|
321
|
-
actions.emit(null);
|
|
322
|
-
return;
|
|
265
|
+
);
|
|
266
|
+
this.add(invalidationDetector, { name: "invalidation_detector" });
|
|
267
|
+
this.addDisposer(keepalive(invalidationDetector));
|
|
268
|
+
const cascade = node(
|
|
269
|
+
[invalidationDetector],
|
|
270
|
+
(batchData, actions, ctx) => {
|
|
271
|
+
const evts = lastOf(batchData[0], ctx.prevData[0]) ?? [];
|
|
272
|
+
actions.emit(evts);
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: "cascade",
|
|
276
|
+
describeKind: "derived",
|
|
277
|
+
initial: [],
|
|
278
|
+
meta: factMeta("cascade_topic", { cycle: "cascade" })
|
|
323
279
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
280
|
+
);
|
|
281
|
+
this.add(cascade, { name: "cascade" });
|
|
282
|
+
this.addDisposer(keepalive(cascade));
|
|
283
|
+
const cascadeOverflow = node([], {
|
|
284
|
+
initial: null,
|
|
285
|
+
name: "cascade_overflow",
|
|
286
|
+
describeKind: "state",
|
|
287
|
+
meta: factMeta("cascade_overflow")
|
|
288
|
+
});
|
|
289
|
+
this.add(cascadeOverflow, { name: "cascade_overflow" });
|
|
290
|
+
this.addDisposer(keepalive(cascadeOverflow));
|
|
291
|
+
const cascadeProcessor = node(
|
|
292
|
+
[cascade],
|
|
293
|
+
(batchData, actions, ctx) => {
|
|
294
|
+
const evts = lastOf(batchData[0], ctx.prevData[0]) ?? [];
|
|
295
|
+
if (evts.length === 0) {
|
|
296
|
+
actions.emit([]);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const byId = /* @__PURE__ */ new Map();
|
|
300
|
+
for (const e of evts) if (!byId.has(e.factId)) byId.set(e.factId, e);
|
|
301
|
+
cascadeIteration += 1;
|
|
302
|
+
if (cascadeIteration > maxIterations) {
|
|
303
|
+
const sample = [...byId.keys()].slice(0, OVERFLOW_SAMPLE_SIZE);
|
|
304
|
+
const rootFactId = evts[0]?.rootFactId ?? "";
|
|
305
|
+
cascadeOverflow.emit({
|
|
306
|
+
droppedCount: byId.size,
|
|
307
|
+
sample,
|
|
308
|
+
rootFactId
|
|
330
309
|
});
|
|
310
|
+
events.append({
|
|
311
|
+
action: "overflow",
|
|
312
|
+
reason: "cascade",
|
|
313
|
+
id: rootFactId,
|
|
314
|
+
t_ns: wallClockNs(),
|
|
315
|
+
seq: bumpCursor(seqCursor)
|
|
316
|
+
});
|
|
317
|
+
actions.emit([]);
|
|
331
318
|
return;
|
|
332
319
|
}
|
|
320
|
+
for (const [id, e] of byId) {
|
|
321
|
+
replaceFragment(
|
|
322
|
+
id,
|
|
323
|
+
(prev) => prev.validTo !== void 0 ? prev : { ...prev, validTo: e.rootValidTo }
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
actions.emit([...byId.values()]);
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: "cascade_processor",
|
|
330
|
+
describeKind: "derived",
|
|
331
|
+
initial: [],
|
|
332
|
+
meta: factMeta("cascade_processor", { cycle: "cascade" })
|
|
333
333
|
}
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
initial: null,
|
|
340
|
-
meta: factMeta("review"),
|
|
341
|
-
// F10a: dedupe on the requested factId (null === no request) so a
|
|
342
|
-
// stable low-confidence fact does not re-emit a review every wave.
|
|
343
|
-
equals: (a, b) => (a?.factId ?? null) === (b?.factId ?? null)
|
|
344
|
-
}
|
|
345
|
-
);
|
|
346
|
-
graph.add(review, { name: "review" });
|
|
347
|
-
graph.addDisposer(keepalive(review));
|
|
348
|
-
if (config.outcome) {
|
|
349
|
-
const outcomeProcessor = node(
|
|
350
|
-
config.scoring ? [config.outcome, config.scoring] : [config.outcome],
|
|
334
|
+
);
|
|
335
|
+
this.add(cascadeProcessor, { name: "cascade_processor" });
|
|
336
|
+
this.addDisposer(keepalive(cascadeProcessor));
|
|
337
|
+
const review = node(
|
|
338
|
+
[factStore],
|
|
351
339
|
(batchData, actions, ctx) => {
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
340
|
+
const fs = lastOf(batchData[0], ctx.prevData[0]);
|
|
341
|
+
if (fs == null) {
|
|
354
342
|
actions.emit(null);
|
|
355
343
|
return;
|
|
356
344
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
nextConf = Math.max(0, Math.min(1, prev.confidence + sig.reward));
|
|
345
|
+
for (const f of fs.byId.values()) {
|
|
346
|
+
if (f.confidence < reviewThreshold && f.validTo === void 0) {
|
|
347
|
+
actions.emit({
|
|
348
|
+
factId: f.id,
|
|
349
|
+
confidence: f.confidence,
|
|
350
|
+
threshold: reviewThreshold
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
366
353
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
actions.emit(sig);
|
|
354
|
+
}
|
|
355
|
+
actions.emit(null);
|
|
370
356
|
},
|
|
371
357
|
{
|
|
372
|
-
name: "
|
|
358
|
+
name: "review",
|
|
373
359
|
describeKind: "derived",
|
|
374
360
|
initial: null,
|
|
375
|
-
meta: factMeta("
|
|
361
|
+
meta: factMeta("review"),
|
|
362
|
+
// F10a: dedupe on the requested factId (null === no request) so a
|
|
363
|
+
// stable low-confidence fact does not re-emit a review every wave.
|
|
364
|
+
equals: (a, b) => (a?.factId ?? null) === (b?.factId ?? null)
|
|
376
365
|
}
|
|
377
366
|
);
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
367
|
+
this.add(review, { name: "review" });
|
|
368
|
+
this.addDisposer(keepalive(review));
|
|
369
|
+
if (config.outcome) {
|
|
370
|
+
const outcomeProcessor = node(
|
|
371
|
+
config.scoring ? [config.outcome, config.scoring] : [config.outcome],
|
|
372
|
+
(batchData, actions, ctx) => {
|
|
373
|
+
const sig = lastOf(batchData[0], ctx.prevData[0]);
|
|
374
|
+
if (sig == null) {
|
|
375
|
+
actions.emit(null);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
replaceFragment(sig.factId, (prev) => {
|
|
379
|
+
let nextConf = prev.confidence;
|
|
380
|
+
if (config.scoring) {
|
|
381
|
+
const policy = lastOf(batchData[1], ctx.prevData[1]);
|
|
382
|
+
if (policy) {
|
|
383
|
+
nextConf = policy(prev, makeReadHandle(allFacts()));
|
|
384
|
+
}
|
|
385
|
+
} else {
|
|
386
|
+
nextConf = Math.max(0, Math.min(1, prev.confidence + sig.reward));
|
|
387
|
+
}
|
|
388
|
+
return { ...prev, confidence: nextConf };
|
|
389
|
+
});
|
|
390
|
+
actions.emit(sig);
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name: "outcome_processor",
|
|
394
|
+
describeKind: "derived",
|
|
395
|
+
initial: null,
|
|
396
|
+
meta: factMeta("outcome")
|
|
398
397
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
});
|
|
403
|
-
results.sort((a, b) => b.confidence - a.confidence || Number(b.t_ns - a.t_ns));
|
|
404
|
-
if (q.limit !== void 0) results = results.slice(0, Math.max(0, q.limit));
|
|
405
|
-
actions.emit({ query: q, results });
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
name: "answer",
|
|
409
|
-
describeKind: "derived",
|
|
410
|
-
initial: null,
|
|
411
|
-
meta: factMeta("query", { role: "output" })
|
|
398
|
+
);
|
|
399
|
+
this.add(outcomeProcessor, { name: "outcome_processor" });
|
|
400
|
+
this.addDisposer(keepalive(outcomeProcessor));
|
|
412
401
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
t_ns: wallClockNs(),
|
|
435
|
-
seq: bumpCursor(seqCursor)
|
|
402
|
+
const answer = node(
|
|
403
|
+
config.query ? [config.query, factStore] : [factStore],
|
|
404
|
+
(batchData, actions, ctx) => {
|
|
405
|
+
if (!config.query) {
|
|
406
|
+
actions.emit(null);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const q = lastOf(batchData[0], ctx.prevData[0]);
|
|
410
|
+
const fs = lastOf(batchData[1], ctx.prevData[1]);
|
|
411
|
+
if (q == null) {
|
|
412
|
+
actions.emit(null);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const store = fs ?? emptyStore();
|
|
416
|
+
let results = [...store.byId.values()].filter((f) => {
|
|
417
|
+
if (q.tags && q.tags.length > 0 && !q.tags.some((t) => f.tags.includes(t))) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
if (q.minConfidence !== void 0 && f.confidence < q.minConfidence) return false;
|
|
421
|
+
if (!currentlyValid(f, q.asOf)) return false;
|
|
422
|
+
return true;
|
|
436
423
|
});
|
|
424
|
+
results.sort((a, b) => b.confidence - a.confidence || Number(b.t_ns - a.t_ns));
|
|
425
|
+
if (q.limit !== void 0) results = results.slice(0, Math.max(0, q.limit));
|
|
426
|
+
actions.emit({ query: q, results });
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: "answer",
|
|
430
|
+
describeKind: "derived",
|
|
431
|
+
initial: null,
|
|
432
|
+
meta: factMeta("query", { role: "output" })
|
|
437
433
|
}
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
initial: [],
|
|
444
|
-
meta: factMeta("consolidator")
|
|
445
|
-
}
|
|
446
|
-
);
|
|
447
|
-
graph.add(consolidated, { name: "consolidated" });
|
|
448
|
-
graph.addDisposer(keepalive(consolidated));
|
|
449
|
-
if (config.decayTrigger) {
|
|
450
|
-
const decayProcessor = node(
|
|
451
|
-
config.decay ? [config.decayTrigger, config.decay] : [config.decayTrigger],
|
|
434
|
+
);
|
|
435
|
+
this.add(answer, { name: "answer" });
|
|
436
|
+
this.addDisposer(keepalive(answer));
|
|
437
|
+
const consolidated = node(
|
|
438
|
+
config.consolidateTrigger ? [config.consolidateTrigger] : [],
|
|
452
439
|
(batchData, actions, ctx) => {
|
|
453
|
-
|
|
454
|
-
|
|
440
|
+
void batchData;
|
|
441
|
+
void ctx;
|
|
442
|
+
if (!config.consolidateTrigger || !config.consolidate) {
|
|
455
443
|
actions.emit([]);
|
|
456
444
|
return;
|
|
457
445
|
}
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
446
|
+
const fragments = config.consolidate(makeReadHandle(allFacts()));
|
|
447
|
+
for (const f of fragments) {
|
|
448
|
+
const deps = config.extractDependencies(f);
|
|
449
|
+
processedRoots.delete(f.id);
|
|
450
|
+
commitFragment(f);
|
|
451
|
+
indexFragment(f, deps);
|
|
452
|
+
events.append({
|
|
453
|
+
action: "consolidate",
|
|
454
|
+
id: f.id,
|
|
455
|
+
t_ns: wallClockNs(),
|
|
456
|
+
seq: bumpCursor(seqCursor)
|
|
457
|
+
});
|
|
468
458
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
459
|
+
actions.emit(fragments);
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
name: "consolidated",
|
|
463
|
+
describeKind: "derived",
|
|
464
|
+
initial: [],
|
|
465
|
+
// Inspection completeness (COMPOSITION-GUIDE §24 "make the
|
|
466
|
+
// invisible edge visible"): `consolidated` write-backs feed the
|
|
467
|
+
// bounded cascade store (commit → shard emit →
|
|
468
|
+
// `invalidationDetector`) exactly like `cascadeProcessor`, but
|
|
469
|
+
// is NOT a cascade-cycle node. `feeds:"cascade"` surfaces it as
|
|
470
|
+
// a cascade-store mutator in `describe()`/`explain()`;
|
|
471
|
+
// `drivesRoot:false` — by the consolidator contract successors
|
|
472
|
+
// are fresh live facts (no `validTo`), so on the contract path
|
|
473
|
+
// they do not root the cascade. (An out-of-contract `consolidate`
|
|
474
|
+
// that emits a `validTo`-set fragment WOULD root it via the
|
|
475
|
+
// detector — the tag reflects the documented contract, not a
|
|
476
|
+
// structural impossibility. Contrast `decay_processor` below,
|
|
477
|
+
// whose `drivesRoot:false` IS structurally provable.)
|
|
478
|
+
meta: factMeta("consolidator", { feeds: "cascade", drivesRoot: false })
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
this.add(consolidated, { name: "consolidated" });
|
|
482
|
+
this.addDisposer(keepalive(consolidated));
|
|
483
|
+
if (config.decayTrigger) {
|
|
484
|
+
const decayProcessor = node(
|
|
485
|
+
config.decay ? [config.decayTrigger, config.decay] : [config.decayTrigger],
|
|
486
|
+
(batchData, actions, ctx) => {
|
|
487
|
+
const policy = config.decay ? lastOf(batchData[1], ctx.prevData[1]) : void 0;
|
|
488
|
+
if (!policy) {
|
|
489
|
+
actions.emit([]);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const now = BigInt(monotonicNs());
|
|
493
|
+
const changes = [];
|
|
494
|
+
for (const f of allFacts().values()) {
|
|
495
|
+
if (f.validTo !== void 0) continue;
|
|
496
|
+
const ageNs = now - f.t_ns;
|
|
497
|
+
const raw = policy(f.confidence, ageNs);
|
|
498
|
+
if (!Number.isFinite(raw)) continue;
|
|
499
|
+
const next = raw < 0 ? 0 : raw > 1 ? 1 : raw;
|
|
500
|
+
if (next === f.confidence) continue;
|
|
501
|
+
changes.push({ id: f.id, next });
|
|
502
|
+
}
|
|
503
|
+
const decayed = [];
|
|
504
|
+
for (const { id, next } of changes) {
|
|
505
|
+
const idx = findShardOf(id);
|
|
506
|
+
const fs = idx < 0 ? void 0 : shards[idx].cache;
|
|
507
|
+
const live = fs?.byId.get(id);
|
|
508
|
+
if (!live || live.validTo !== void 0) continue;
|
|
509
|
+
replaceFragment(
|
|
510
|
+
id,
|
|
511
|
+
(prev) => prev.validTo !== void 0 ? prev : { ...prev, confidence: next }
|
|
512
|
+
);
|
|
513
|
+
decayed.push({ ...live, confidence: next });
|
|
514
|
+
}
|
|
515
|
+
if (decayed.length > 0) {
|
|
516
|
+
events.append({
|
|
517
|
+
action: "decay",
|
|
518
|
+
t_ns: wallClockNs(),
|
|
519
|
+
seq: bumpCursor(seqCursor),
|
|
520
|
+
count: decayed.length
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
actions.emit(decayed);
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
name: "decay_processor",
|
|
527
|
+
describeKind: "derived",
|
|
528
|
+
initial: [],
|
|
529
|
+
// Inspection completeness (same convention as `consolidated`
|
|
530
|
+
// above — kept uniform): `decay_processor` write-backs feed
|
|
531
|
+
// the cascade store via `replaceFragment` → shard emit →
|
|
532
|
+
// `invalidationDetector`. `feeds:"cascade"` surfaces it as a
|
|
533
|
+
// cascade-store mutator; `drivesRoot:false` — decay only
|
|
534
|
+
// mutates `confidence`, never `validTo`, and the detector
|
|
535
|
+
// roots on `validTo` only, so it provably cannot root.
|
|
536
|
+
meta: factMeta("decay", { feeds: "cascade", drivesRoot: false })
|
|
480
537
|
}
|
|
481
|
-
|
|
538
|
+
);
|
|
539
|
+
this.add(decayProcessor, { name: "decay_processor" });
|
|
540
|
+
this.addDisposer(keepalive(decayProcessor));
|
|
541
|
+
}
|
|
542
|
+
const ingestAudit = node(
|
|
543
|
+
[extractOp],
|
|
544
|
+
(batchData, actions, ctx) => {
|
|
545
|
+
const f = lastOf(batchData[0], ctx.prevData[0]);
|
|
546
|
+
if (f != null) {
|
|
482
547
|
events.append({
|
|
483
|
-
action: "
|
|
548
|
+
action: "ingest",
|
|
549
|
+
id: f.id,
|
|
484
550
|
t_ns: wallClockNs(),
|
|
485
551
|
seq: bumpCursor(seqCursor)
|
|
486
552
|
});
|
|
553
|
+
ingestLog?.append(f);
|
|
487
554
|
}
|
|
488
|
-
actions.emit(
|
|
555
|
+
actions.emit(f ?? null);
|
|
489
556
|
},
|
|
490
557
|
{
|
|
491
|
-
name: "
|
|
558
|
+
name: "_ingest_audit",
|
|
492
559
|
describeKind: "derived",
|
|
493
|
-
initial:
|
|
494
|
-
meta: factMeta("
|
|
560
|
+
initial: null,
|
|
561
|
+
meta: factMeta("audit")
|
|
495
562
|
}
|
|
496
563
|
);
|
|
497
|
-
|
|
498
|
-
|
|
564
|
+
this.add(ingestAudit, { name: "_ingest_audit" });
|
|
565
|
+
this.addDisposer(keepalive(ingestAudit));
|
|
566
|
+
this.shards = shards;
|
|
567
|
+
this.factStore = factStore;
|
|
568
|
+
this.dependentsIndex = dependentsIndex;
|
|
569
|
+
this.answer = answer;
|
|
570
|
+
this.cascade = cascade;
|
|
571
|
+
this.cascadeOverflow = cascadeOverflow;
|
|
572
|
+
this.review = review;
|
|
573
|
+
this.consolidated = consolidated;
|
|
574
|
+
this.events = events;
|
|
575
|
+
if (ingestLog) this.ingestLog = ingestLog;
|
|
499
576
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
const f = lastOf(batchData[0], ctx.prevData[0]);
|
|
504
|
-
if (f != null) {
|
|
505
|
-
events.append({
|
|
506
|
-
action: "ingest",
|
|
507
|
-
id: f.id,
|
|
508
|
-
t_ns: wallClockNs(),
|
|
509
|
-
seq: bumpCursor(seqCursor)
|
|
510
|
-
});
|
|
511
|
-
ingestLog?.append(f);
|
|
512
|
-
}
|
|
513
|
-
actions.emit(f ?? null);
|
|
514
|
-
},
|
|
515
|
-
{
|
|
516
|
-
name: "_ingest_audit",
|
|
517
|
-
describeKind: "derived",
|
|
518
|
-
initial: null,
|
|
519
|
-
meta: factMeta("audit")
|
|
520
|
-
}
|
|
521
|
-
);
|
|
522
|
-
graph.add(ingestAudit, { name: "_ingest_audit" });
|
|
523
|
-
graph.addDisposer(keepalive(ingestAudit));
|
|
524
|
-
function itemNode(id) {
|
|
577
|
+
// ── itemNode reactive read ───────────────────────────────────────────
|
|
578
|
+
/** Reactive read: a single fact by id (SENTINEL until the fact exists). */
|
|
579
|
+
itemNode(id) {
|
|
525
580
|
return node(
|
|
526
|
-
[factStore],
|
|
581
|
+
[this.factStore],
|
|
527
582
|
(batchData, actions, ctx) => {
|
|
528
583
|
const fs = lastOf(batchData[0], ctx.prevData[0]);
|
|
529
584
|
actions.emit(fs?.byId.get(id));
|
|
@@ -535,20 +590,9 @@ function reactiveFactStore(config) {
|
|
|
535
590
|
}
|
|
536
591
|
);
|
|
537
592
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
dependentsIndex,
|
|
542
|
-
answer,
|
|
543
|
-
cascade,
|
|
544
|
-
cascadeOverflow,
|
|
545
|
-
review,
|
|
546
|
-
consolidated,
|
|
547
|
-
events,
|
|
548
|
-
...ingestLog ? { ingestLog } : {},
|
|
549
|
-
itemNode
|
|
550
|
-
});
|
|
551
|
-
return out;
|
|
593
|
+
};
|
|
594
|
+
function reactiveFactStore(config) {
|
|
595
|
+
return new ReactiveFactStoreGraph(config);
|
|
552
596
|
}
|
|
553
597
|
|
|
554
598
|
// src/utils/memory/persistent-fact-store.ts
|
|
@@ -972,6 +1016,52 @@ function shardByTenant(tenantOf, opts = {}) {
|
|
|
972
1016
|
return { shardBy: (f) => tenantOf(f), shardCount };
|
|
973
1017
|
}
|
|
974
1018
|
|
|
1019
|
+
// src/utils/memory/simple-fact-store.ts
|
|
1020
|
+
import { monotonicNs as monotonicNs2, node as node9 } from "@graphrefly/pure-ts/core";
|
|
1021
|
+
var DEFAULT_DECAY_HALF_LIFE_NS = 604800000000000n;
|
|
1022
|
+
var DEFAULT_DECAY_PERIOD_MS = 36e5;
|
|
1023
|
+
function simpleFactStore(opts = {}) {
|
|
1024
|
+
const ingest = node9([], { initial: void 0 });
|
|
1025
|
+
const extractDependencies = opts.extractDependencies ?? (() => []);
|
|
1026
|
+
const consolidationCfg = opts.consolidate ? consolidationRem(opts.consolidate) : void 0;
|
|
1027
|
+
const baseCfg = {
|
|
1028
|
+
ingest,
|
|
1029
|
+
extractDependencies,
|
|
1030
|
+
...consolidationCfg ?? {}
|
|
1031
|
+
};
|
|
1032
|
+
const mem = opts.storage ? persistentReactiveFactStore({
|
|
1033
|
+
...baseCfg,
|
|
1034
|
+
storage: opts.storage,
|
|
1035
|
+
...opts.persistName !== void 0 ? { persistName: opts.persistName } : {},
|
|
1036
|
+
...opts.codec !== void 0 ? { codec: opts.codec } : {}
|
|
1037
|
+
}) : reactiveFactStore(baseCfg);
|
|
1038
|
+
if (opts.decay !== false) {
|
|
1039
|
+
const d = opts.decay ?? {};
|
|
1040
|
+
decayExponential(mem, ingest, {
|
|
1041
|
+
...d,
|
|
1042
|
+
halfLifeNs: d.halfLifeNs ?? DEFAULT_DECAY_HALF_LIFE_NS,
|
|
1043
|
+
periodMs: d.periodMs ?? DEFAULT_DECAY_PERIOD_MS
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
const remember = (id, payload, ro) => {
|
|
1047
|
+
const fragment = {
|
|
1048
|
+
id,
|
|
1049
|
+
payload,
|
|
1050
|
+
t_ns: BigInt(monotonicNs2()),
|
|
1051
|
+
confidence: ro?.confidence ?? 1,
|
|
1052
|
+
tags: ro?.tags ?? [],
|
|
1053
|
+
sources: ro?.sources ?? [],
|
|
1054
|
+
...ro?.validTo !== void 0 ? { validTo: ro.validTo } : {},
|
|
1055
|
+
...ro?.validFrom !== void 0 ? { validFrom: ro.validFrom } : {},
|
|
1056
|
+
...ro?.provenance !== void 0 ? { provenance: ro.provenance } : {}
|
|
1057
|
+
};
|
|
1058
|
+
ingest.emit(fragment);
|
|
1059
|
+
};
|
|
1060
|
+
const out = mem;
|
|
1061
|
+
out.remember = remember;
|
|
1062
|
+
return out;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
975
1065
|
// src/utils/memory/index.ts
|
|
976
1066
|
var NS_PER_SEC = 1e9;
|
|
977
1067
|
function memoryMeta(kind, extra) {
|
|
@@ -979,7 +1069,7 @@ function memoryMeta(kind, extra) {
|
|
|
979
1069
|
}
|
|
980
1070
|
function toNode(v, name) {
|
|
981
1071
|
if (v instanceof NodeImpl) return v;
|
|
982
|
-
return
|
|
1072
|
+
return node10([], { initial: v, ...name ? { name } : void 0 });
|
|
983
1073
|
}
|
|
984
1074
|
function ageSeconds(now, lastNs) {
|
|
985
1075
|
return (now - lastNs) / NS_PER_SEC;
|
|
@@ -1039,7 +1129,7 @@ function collection(name, opts = {}) {
|
|
|
1039
1129
|
return scoreInput;
|
|
1040
1130
|
};
|
|
1041
1131
|
const graph = new Graph2(name);
|
|
1042
|
-
const retentionScore = (_k, v) => ranked ? decay(v.baseScore, ageSeconds(
|
|
1132
|
+
const retentionScore = (_k, v) => ranked ? decay(v.baseScore, ageSeconds(monotonicNs3(), v.lastAccessNs), decayRate, minScore) : v.lastAccessNs;
|
|
1043
1133
|
const items = reactiveMap({
|
|
1044
1134
|
name: "items",
|
|
1045
1135
|
...maxSize !== void 0 ? { retention: { score: retentionScore, maxSize } } : {}
|
|
@@ -1049,15 +1139,15 @@ function collection(name, opts = {}) {
|
|
|
1049
1139
|
if (ranked && decayRate > 0) {
|
|
1050
1140
|
const intervalMs = opts.refreshIntervalMs ?? Math.max(1, 1e3 * Math.LN2 / (10 * decayRate));
|
|
1051
1141
|
const tickCounter = fromTimer3(intervalMs, { period: intervalMs });
|
|
1052
|
-
refreshTick =
|
|
1142
|
+
refreshTick = node10(
|
|
1053
1143
|
[tickCounter],
|
|
1054
1144
|
(_batchData, actions) => {
|
|
1055
|
-
actions.emit(
|
|
1145
|
+
actions.emit(monotonicNs3());
|
|
1056
1146
|
},
|
|
1057
1147
|
{
|
|
1058
1148
|
name: "refresh_tick_ns",
|
|
1059
1149
|
describeKind: "derived",
|
|
1060
|
-
initial:
|
|
1150
|
+
initial: monotonicNs3(),
|
|
1061
1151
|
meta: memoryMeta("clock")
|
|
1062
1152
|
}
|
|
1063
1153
|
);
|
|
@@ -1068,7 +1158,7 @@ function collection(name, opts = {}) {
|
|
|
1068
1158
|
const rankedDeps = [items.entries];
|
|
1069
1159
|
if (refreshTick) rankedDeps.push(refreshTick);
|
|
1070
1160
|
if (scoreNode) rankedDeps.push(scoreNode);
|
|
1071
|
-
rankedNode =
|
|
1161
|
+
rankedNode = node10(
|
|
1072
1162
|
rankedDeps,
|
|
1073
1163
|
(batchData, actions, ctx) => {
|
|
1074
1164
|
const values = batchData.map(
|
|
@@ -1078,9 +1168,9 @@ function collection(name, opts = {}) {
|
|
|
1078
1168
|
let now;
|
|
1079
1169
|
if (refreshTick) {
|
|
1080
1170
|
const tickValue = values[1];
|
|
1081
|
-
now = typeof tickValue === "number" ? tickValue :
|
|
1171
|
+
now = typeof tickValue === "number" ? tickValue : monotonicNs3();
|
|
1082
1172
|
} else {
|
|
1083
|
-
now =
|
|
1173
|
+
now = monotonicNs3();
|
|
1084
1174
|
}
|
|
1085
1175
|
if (!snapshot || snapshot.size === 0) {
|
|
1086
1176
|
actions.emit([]);
|
|
@@ -1105,7 +1195,7 @@ function collection(name, opts = {}) {
|
|
|
1105
1195
|
);
|
|
1106
1196
|
graph.add(rankedNode, { name: "ranked" });
|
|
1107
1197
|
} else {
|
|
1108
|
-
rankedNode =
|
|
1198
|
+
rankedNode = node10([], {
|
|
1109
1199
|
initial: [],
|
|
1110
1200
|
name: "ranked",
|
|
1111
1201
|
describeKind: "state",
|
|
@@ -1113,7 +1203,7 @@ function collection(name, opts = {}) {
|
|
|
1113
1203
|
});
|
|
1114
1204
|
graph.add(rankedNode, { name: "ranked" });
|
|
1115
1205
|
}
|
|
1116
|
-
const size =
|
|
1206
|
+
const size = node10(
|
|
1117
1207
|
[items.entries],
|
|
1118
1208
|
(batchData, actions, ctx) => {
|
|
1119
1209
|
const data = batchData.map(
|
|
@@ -1138,7 +1228,7 @@ function collection(name, opts = {}) {
|
|
|
1138
1228
|
});
|
|
1139
1229
|
const seqCursor = registerCursor(graph, "seq", 0);
|
|
1140
1230
|
const upsertImpl = (id, value, _opts) => {
|
|
1141
|
-
const now =
|
|
1231
|
+
const now = monotonicNs3();
|
|
1142
1232
|
const prev = items.get(id);
|
|
1143
1233
|
const baseScore = _opts?.score ?? readScoreFn()(value);
|
|
1144
1234
|
items.set(id, {
|
|
@@ -1194,7 +1284,7 @@ function collection(name, opts = {}) {
|
|
|
1194
1284
|
});
|
|
1195
1285
|
function itemNode(id) {
|
|
1196
1286
|
const idN = toNode(id, "id");
|
|
1197
|
-
return
|
|
1287
|
+
return node10(
|
|
1198
1288
|
[items.entries, idN],
|
|
1199
1289
|
(batchData, actions, ctx) => {
|
|
1200
1290
|
const data = batchData.map(
|
|
@@ -1212,7 +1302,7 @@ function collection(name, opts = {}) {
|
|
|
1212
1302
|
}
|
|
1213
1303
|
function hasNode(id) {
|
|
1214
1304
|
const idN = toNode(id, "id");
|
|
1215
|
-
return
|
|
1305
|
+
return node10(
|
|
1216
1306
|
[items.entries, idN],
|
|
1217
1307
|
(batchData, actions, ctx) => {
|
|
1218
1308
|
const data = batchData.map(
|
|
@@ -1324,7 +1414,7 @@ function vectorIndex(opts = {}) {
|
|
|
1324
1414
|
id,
|
|
1325
1415
|
vector: [...vector],
|
|
1326
1416
|
...copiedMeta !== void 0 ? { meta: copiedMeta } : {},
|
|
1327
|
-
upsertedAtNs:
|
|
1417
|
+
upsertedAtNs: monotonicNs3()
|
|
1328
1418
|
};
|
|
1329
1419
|
entries.set(id, record);
|
|
1330
1420
|
};
|
|
@@ -1380,7 +1470,7 @@ function vectorIndex(opts = {}) {
|
|
|
1380
1470
|
});
|
|
1381
1471
|
function searchNode(query, k = 5) {
|
|
1382
1472
|
const kN = toNode(k, "k");
|
|
1383
|
-
return
|
|
1473
|
+
return node10(
|
|
1384
1474
|
[entries.entries, query, kN],
|
|
1385
1475
|
(batchData, actions, ctx) => {
|
|
1386
1476
|
const values = batchData.map(
|
|
@@ -1496,7 +1586,7 @@ function knowledgeGraph(name, opts = {}) {
|
|
|
1496
1586
|
});
|
|
1497
1587
|
graph.add(entitiesMap.entries, { name: "entities" });
|
|
1498
1588
|
graph.add(edgesMap.entries, { name: "edges" });
|
|
1499
|
-
const adjacencyOut =
|
|
1589
|
+
const adjacencyOut = node10(
|
|
1500
1590
|
[edgesMap.entries],
|
|
1501
1591
|
(batchData, actions, ctx) => {
|
|
1502
1592
|
const data = batchData.map(
|
|
@@ -1513,7 +1603,7 @@ function knowledgeGraph(name, opts = {}) {
|
|
|
1513
1603
|
meta: memoryMeta("adjacency_out")
|
|
1514
1604
|
}
|
|
1515
1605
|
);
|
|
1516
|
-
const adjacencyIn =
|
|
1606
|
+
const adjacencyIn = node10(
|
|
1517
1607
|
[edgesMap.entries],
|
|
1518
1608
|
(batchData, actions, ctx) => {
|
|
1519
1609
|
const data = batchData.map(
|
|
@@ -1534,7 +1624,7 @@ function knowledgeGraph(name, opts = {}) {
|
|
|
1534
1624
|
graph.add(adjacencyIn, { name: "adjacencyIn" });
|
|
1535
1625
|
graph.addDisposer(keepalive6(adjacencyOut));
|
|
1536
1626
|
graph.addDisposer(keepalive6(adjacencyIn));
|
|
1537
|
-
const entityCount =
|
|
1627
|
+
const entityCount = node10(
|
|
1538
1628
|
[entitiesMap.entries],
|
|
1539
1629
|
(batchData, actions, ctx) => {
|
|
1540
1630
|
const data = batchData.map(
|
|
@@ -1545,7 +1635,7 @@ function knowledgeGraph(name, opts = {}) {
|
|
|
1545
1635
|
},
|
|
1546
1636
|
{ name: "entityCount", describeKind: "derived", initial: 0, meta: memoryMeta("entity_count") }
|
|
1547
1637
|
);
|
|
1548
|
-
const edgeCount =
|
|
1638
|
+
const edgeCount = node10(
|
|
1549
1639
|
[edgesMap.entries],
|
|
1550
1640
|
(batchData, actions, ctx) => {
|
|
1551
1641
|
const data = batchData.map(
|
|
@@ -1677,7 +1767,7 @@ function knowledgeGraph(name, opts = {}) {
|
|
|
1677
1767
|
const idN = toNode(id, "id");
|
|
1678
1768
|
const relN = relation !== void 0 ? toNode(relation, "relation") : void 0;
|
|
1679
1769
|
const deps = relN ? [adjacencyOut, adjacencyIn, idN, relN] : [adjacencyOut, adjacencyIn, idN];
|
|
1680
|
-
return
|
|
1770
|
+
return node10(
|
|
1681
1771
|
deps,
|
|
1682
1772
|
(batchData, actions, ctx) => {
|
|
1683
1773
|
const values = batchData.map(
|
|
@@ -1745,6 +1835,7 @@ function knowledgeGraph(name, opts = {}) {
|
|
|
1745
1835
|
}
|
|
1746
1836
|
|
|
1747
1837
|
export {
|
|
1838
|
+
ReactiveFactStoreGraph,
|
|
1748
1839
|
reactiveFactStore,
|
|
1749
1840
|
persistentReactiveFactStore,
|
|
1750
1841
|
admissionLlmJudge,
|
|
@@ -1755,9 +1846,12 @@ export {
|
|
|
1755
1846
|
invalidationTracer,
|
|
1756
1847
|
scoringByOutcome,
|
|
1757
1848
|
shardByTenant,
|
|
1849
|
+
DEFAULT_DECAY_HALF_LIFE_NS,
|
|
1850
|
+
DEFAULT_DECAY_PERIOD_MS,
|
|
1851
|
+
simpleFactStore,
|
|
1758
1852
|
cosineSimilarity,
|
|
1759
1853
|
collection,
|
|
1760
1854
|
vectorIndex,
|
|
1761
1855
|
knowledgeGraph
|
|
1762
1856
|
};
|
|
1763
|
-
//# sourceMappingURL=chunk-
|
|
1857
|
+
//# sourceMappingURL=chunk-K4ZYJ4EM.js.map
|