@graphrefly/graphrefly 0.21.0 → 0.23.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/README.md +7 -5
- package/dist/chunk-263BEJJO.js +115 -0
- package/dist/chunk-263BEJJO.js.map +1 -0
- package/dist/chunk-2GQLMQVJ.js +47 -0
- package/dist/chunk-2GQLMQVJ.js.map +1 -0
- package/dist/chunk-32N5A454.js +36 -0
- package/dist/chunk-32N5A454.js.map +1 -0
- package/dist/chunk-7TAQJHQV.js +103 -0
- package/dist/chunk-7TAQJHQV.js.map +1 -0
- package/dist/{chunk-VOQFK7YN.js → chunk-CWYPA63G.js} +109 -259
- package/dist/chunk-CWYPA63G.js.map +1 -0
- package/dist/{chunk-7IGHIFTT.js → chunk-HVBX5KIW.js} +15 -26
- package/dist/chunk-HVBX5KIW.js.map +1 -0
- package/dist/chunk-JFONSPNF.js +391 -0
- package/dist/chunk-JFONSPNF.js.map +1 -0
- package/dist/chunk-NZMBRXQV.js +2330 -0
- package/dist/chunk-NZMBRXQV.js.map +1 -0
- package/dist/{chunk-XWBVAO2R.js → chunk-PNUZM7PC.js} +20 -30
- package/dist/chunk-PNUZM7PC.js.map +1 -0
- package/dist/{chunk-ZTCDY5NQ.js → chunk-PX6PDUJ5.js} +34 -50
- package/dist/chunk-PX6PDUJ5.js.map +1 -0
- package/dist/chunk-XRFJJ2IU.js +2417 -0
- package/dist/chunk-XRFJJ2IU.js.map +1 -0
- package/dist/chunk-XTLYW4FR.js +6829 -0
- package/dist/chunk-XTLYW4FR.js.map +1 -0
- package/dist/compat/nestjs/index.cjs +3489 -2286
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +6 -4
- package/dist/compat/nestjs/index.d.ts +6 -4
- package/dist/compat/nestjs/index.js +10 -8
- package/dist/core/index.cjs +1706 -1217
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -2
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.js +37 -34
- package/dist/extra/index.cjs +7519 -6125
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +4 -4
- package/dist/extra/index.d.ts +4 -4
- package/dist/extra/index.js +63 -34
- package/dist/graph/index.cjs +3199 -2212
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +5 -3
- package/dist/graph/index.d.ts +5 -3
- package/dist/graph/index.js +24 -11
- package/dist/graph-BtdSRHUc.d.cts +1128 -0
- package/dist/graph-CEO2FkLY.d.ts +1128 -0
- package/dist/{index-DuN3bhtm.d.ts → index-B0tfuXwV.d.cts} +1697 -586
- package/dist/index-BFGjXbiP.d.cts +315 -0
- package/dist/{index-CgSiUouz.d.ts → index-BPlWVAKY.d.cts} +4 -4
- package/dist/index-BUj3ASVe.d.cts +406 -0
- package/dist/{index-VHA43cGP.d.cts → index-C59uSJAH.d.cts} +2 -2
- package/dist/index-CkElcUY6.d.ts +315 -0
- package/dist/index-DSPc5rkv.d.ts +406 -0
- package/dist/{index-BjtlNirP.d.cts → index-DgscL7v0.d.ts} +4 -4
- package/dist/{index-SFzE_KTa.d.cts → index-RXN94sHK.d.ts} +1697 -586
- package/dist/{index-8a605sg9.d.ts → index-jEtF4N7L.d.ts} +2 -2
- package/dist/index.cjs +9947 -7949
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +214 -37
- package/dist/index.d.ts +214 -37
- package/dist/index.js +919 -648
- package/dist/index.js.map +1 -1
- package/dist/meta-3QjzotRv.d.ts +41 -0
- package/dist/meta-B-Lbs4-O.d.cts +41 -0
- package/dist/node-C7PD3sn9.d.cts +1188 -0
- package/dist/node-C7PD3sn9.d.ts +1188 -0
- package/dist/{observable-DcBwQY7t.d.ts → observable-EyO-moQY.d.ts} +1 -1
- package/dist/{observable-C8Kx_O6k.d.cts → observable-axpzv1K2.d.cts} +1 -1
- package/dist/patterns/reactive-layout/index.cjs +3205 -2138
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +5 -3
- package/dist/patterns/reactive-layout/index.d.ts +5 -3
- package/dist/patterns/reactive-layout/index.js +7 -4
- package/dist/storage-CHT5WE9m.d.ts +182 -0
- package/dist/storage-DIgAr7M_.d.cts +182 -0
- package/package.json +2 -1
- package/dist/chunk-2UDLYZHT.js +0 -2117
- package/dist/chunk-2UDLYZHT.js.map +0 -1
- package/dist/chunk-4MQ2J6IG.js +0 -1631
- package/dist/chunk-4MQ2J6IG.js.map +0 -1
- package/dist/chunk-7IGHIFTT.js.map +0 -1
- package/dist/chunk-DOSLSFKL.js +0 -162
- package/dist/chunk-DOSLSFKL.js.map +0 -1
- package/dist/chunk-ECN37NVS.js +0 -6227
- package/dist/chunk-ECN37NVS.js.map +0 -1
- package/dist/chunk-G66H6ZRK.js +0 -111
- package/dist/chunk-G66H6ZRK.js.map +0 -1
- package/dist/chunk-VOQFK7YN.js.map +0 -1
- package/dist/chunk-WZ2Z2CRV.js +0 -32
- package/dist/chunk-WZ2Z2CRV.js.map +0 -1
- package/dist/chunk-XWBVAO2R.js.map +0 -1
- package/dist/chunk-ZTCDY5NQ.js.map +0 -1
- package/dist/graph-KsTe57nI.d.cts +0 -750
- package/dist/graph-mILUUqW8.d.ts +0 -750
- package/dist/index-B2SvPEbc.d.ts +0 -257
- package/dist/index-BHfg_Ez3.d.ts +0 -629
- package/dist/index-Bc_diYYJ.d.cts +0 -629
- package/dist/index-UudxGnzc.d.cts +0 -257
- package/dist/meta-BnG7XAaE.d.cts +0 -778
- package/dist/meta-BnG7XAaE.d.ts +0 -778
|
@@ -0,0 +1,1128 @@
|
|
|
1
|
+
import { k as GraphReFlyConfig, a6 as VersioningLevel, N as Node, A as Actor, t as Messages, K as NodeSink } from './node-C7PD3sn9.cjs';
|
|
2
|
+
import { b as DescribeNodeOutput, D as DescribeDetail, a as DescribeField } from './meta-B-Lbs4-O.cjs';
|
|
3
|
+
import { a as StorageTier, S as StorageHandle } from './storage-DIgAr7M_.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Graph profiling and inspection utilities.
|
|
7
|
+
*
|
|
8
|
+
* Provides per-node memory estimation, connectivity stats, and hotspot
|
|
9
|
+
* detection. Non-invasive — reads from `describe()` and node internals
|
|
10
|
+
* without modifying state.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Per-node profile entry. */
|
|
16
|
+
interface NodeProfile {
|
|
17
|
+
/** Qualified path within the graph. */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Node type (state, derived, producer, effect). */
|
|
20
|
+
type: string;
|
|
21
|
+
/** Node status (disconnected, dirty, settled, errored, completed). */
|
|
22
|
+
status: string;
|
|
23
|
+
/** Approximate retained bytes for the node's cached value. */
|
|
24
|
+
valueSizeBytes: number;
|
|
25
|
+
/** Number of downstream subscribers (sinks). */
|
|
26
|
+
subscriberCount: number;
|
|
27
|
+
/** Number of upstream dependencies. */
|
|
28
|
+
depCount: number;
|
|
29
|
+
/**
|
|
30
|
+
* True if this is an effect node with no external subscribers — a classic
|
|
31
|
+
* leak pattern. See {@link GraphProfileResult.orphans} for the broader
|
|
32
|
+
* orphan-node detection across `derived` / `producer` / `effect`.
|
|
33
|
+
*/
|
|
34
|
+
isOrphanEffect: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Orphan category (batch 8 Unit 13 D). `null` when the node is healthy.
|
|
37
|
+
* - `"orphan-effect"` — effect with zero subscribers (pre-existing class).
|
|
38
|
+
* - `"idle-derived"` — derived with zero subscribers (wasted compute path
|
|
39
|
+
* if it ever activates; may indicate a factory forgot keepalive).
|
|
40
|
+
* - `"idle-producer"` — producer with zero subscribers (no external
|
|
41
|
+
* consumer; may be an over-eager factory or forgotten cleanup).
|
|
42
|
+
*/
|
|
43
|
+
orphanKind: "orphan-effect" | "idle-derived" | "idle-producer" | null;
|
|
44
|
+
}
|
|
45
|
+
/** Aggregate graph profile. */
|
|
46
|
+
interface GraphProfileResult {
|
|
47
|
+
/** Total node count. */
|
|
48
|
+
nodeCount: number;
|
|
49
|
+
/** Total edge count. */
|
|
50
|
+
edgeCount: number;
|
|
51
|
+
/** Subgraph count. */
|
|
52
|
+
subgraphCount: number;
|
|
53
|
+
/** All node profiles. */
|
|
54
|
+
nodes: NodeProfile[];
|
|
55
|
+
/** Total approximate value memory across all nodes. */
|
|
56
|
+
totalValueSizeBytes: number;
|
|
57
|
+
/**
|
|
58
|
+
* Top-N hotspots by dimension. Each list is sorted descending. See
|
|
59
|
+
* {@link GraphProfileOptions.topN} for the cap (default 10).
|
|
60
|
+
*/
|
|
61
|
+
hotspots: {
|
|
62
|
+
byValueSize: NodeProfile[];
|
|
63
|
+
bySubscriberCount: NodeProfile[];
|
|
64
|
+
byDepCount: NodeProfile[];
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Every orphan across types — `effect`, `derived`, `producer` with zero
|
|
68
|
+
* subscribers. See {@link NodeProfile.orphanKind} for category.
|
|
69
|
+
*/
|
|
70
|
+
orphans: NodeProfile[];
|
|
71
|
+
/** Effect nodes with no external subscribers (legacy; subset of `orphans`). */
|
|
72
|
+
orphanEffects: NodeProfile[];
|
|
73
|
+
}
|
|
74
|
+
/** Options for {@link graphProfile}. */
|
|
75
|
+
interface GraphProfileOptions {
|
|
76
|
+
/** Limit hotspot list (default 10). */
|
|
77
|
+
topN?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Profile a graph's memory and connectivity characteristics.
|
|
81
|
+
*
|
|
82
|
+
* Uses `describe({ detail: "standard" })` for node metadata and direct
|
|
83
|
+
* `NodeImpl` access for subscriber counts and cached values.
|
|
84
|
+
*
|
|
85
|
+
* @param graph - The graph to profile.
|
|
86
|
+
* @param opts - Optional configuration.
|
|
87
|
+
* @returns Aggregate profile with per-node details, hotspots (multi-dim), and orphans.
|
|
88
|
+
*/
|
|
89
|
+
declare function graphProfile(graph: Graph, opts?: GraphProfileOptions): GraphProfileResult;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Reserved segment for meta companion paths: `nodeName::__meta__::metaKey` (GRAPHREFLY-SPEC §3.6).
|
|
93
|
+
* Forbidden as a local node or mount name.
|
|
94
|
+
*/
|
|
95
|
+
declare const GRAPH_META_SEGMENT = "__meta__";
|
|
96
|
+
/**
|
|
97
|
+
* Options for {@link Graph}. Named fields documented below; the open index
|
|
98
|
+
* signature is preserved so callers can stash extension data on the graph
|
|
99
|
+
* without losing type discipline on the reserved names.
|
|
100
|
+
*
|
|
101
|
+
* - `config` — bind this graph to a specific {@link GraphReFlyConfig} for
|
|
102
|
+
* tier/metaPassthrough/inspector lookups. Defaults to the singleton
|
|
103
|
+
* `defaultConfig` exported from `core/node.ts`.
|
|
104
|
+
* - `versioning` — convenience for `graph.setVersioning(level)` at
|
|
105
|
+
* construction time. Monotonic bulk-apply; see {@link Graph.setVersioning}.
|
|
106
|
+
* - `factories` — reserved for future per-graph factory registration;
|
|
107
|
+
* currently factories flow through `Graph.fromSnapshot(data, {factories})`.
|
|
108
|
+
*/
|
|
109
|
+
interface GraphOptions {
|
|
110
|
+
config?: GraphReFlyConfig;
|
|
111
|
+
versioning?: VersioningLevel;
|
|
112
|
+
factories?: Record<string, GraphNodeFactory>;
|
|
113
|
+
/**
|
|
114
|
+
* Capacity of the reasoning-trace ring buffer. Default: `1000`. Set lower
|
|
115
|
+
* to reduce memory; higher for audit-heavy workloads. Set at construction
|
|
116
|
+
* time — not mutable afterward (ring buffers can't resize cleanly).
|
|
117
|
+
*/
|
|
118
|
+
traceCapacity?: number;
|
|
119
|
+
[key: string]: unknown;
|
|
120
|
+
}
|
|
121
|
+
/** Filter for {@link Graph.describe} — object-style partial match or predicate. */
|
|
122
|
+
type DescribeFilter = Partial<Pick<DescribeNodeOutput, "type" | "status">> | {
|
|
123
|
+
type?: DescribeNodeOutput["type"];
|
|
124
|
+
status?: DescribeNodeOutput["status"];
|
|
125
|
+
/** Keep nodes whose `deps` includes this qualified path. */
|
|
126
|
+
depsIncludes?: string;
|
|
127
|
+
/** Snake-case alias for `depsIncludes` (Python parity). */
|
|
128
|
+
deps_includes?: string;
|
|
129
|
+
/** Keep nodes whose `meta` contains this key. */
|
|
130
|
+
metaHas?: string;
|
|
131
|
+
/** Snake-case alias for `metaHas` (Python parity). */
|
|
132
|
+
meta_has?: string;
|
|
133
|
+
} | ((node: DescribeNodeOutput) => boolean) | ((nodePath: string, node: DescribeNodeOutput) => boolean);
|
|
134
|
+
/** Options for {@link Graph.signal} and {@link Graph.set} (actor context, internal lifecycle). */
|
|
135
|
+
type GraphActorOptions = {
|
|
136
|
+
actor?: Actor;
|
|
137
|
+
/**
|
|
138
|
+
* When `true`, skips node guards (graph lifecycle TEARDOWN, unmount teardown, etc.).
|
|
139
|
+
*/
|
|
140
|
+
internal?: boolean;
|
|
141
|
+
};
|
|
142
|
+
/** Options for {@link Graph.describe} (Phase 3.3b progressive disclosure). */
|
|
143
|
+
type GraphDescribeOptions = {
|
|
144
|
+
actor?: Actor;
|
|
145
|
+
/**
|
|
146
|
+
* Node filter. Filters operate on whatever fields the chosen `detail` level
|
|
147
|
+
* provides. For `metaHas` and `status` filters, use `detail: "standard"` or
|
|
148
|
+
* higher — at `"minimal"` those fields are absent and the filter silently
|
|
149
|
+
* excludes all nodes.
|
|
150
|
+
*/
|
|
151
|
+
filter?: DescribeFilter;
|
|
152
|
+
/**
|
|
153
|
+
* Detail level (Phase 3.3b). Default: `"minimal"`.
|
|
154
|
+
* - `"minimal"` — type + deps only
|
|
155
|
+
* - `"standard"` — type, status, value, deps, meta, versioning (`v`)
|
|
156
|
+
* - `"full"` — standard + guard, lastMutation
|
|
157
|
+
*/
|
|
158
|
+
detail?: DescribeDetail;
|
|
159
|
+
/**
|
|
160
|
+
* Explicit field selection (GraphQL-style). Overrides `detail` when provided.
|
|
161
|
+
* Dotted paths like `"meta.label"` select specific meta keys.
|
|
162
|
+
*/
|
|
163
|
+
fields?: DescribeField[];
|
|
164
|
+
/**
|
|
165
|
+
* Output format.
|
|
166
|
+
* - `undefined` / omitted — return the full {@link GraphDescribeOutput} object.
|
|
167
|
+
* - `"spec"` — GraphSpec input format (object; no status/value, deps as edges).
|
|
168
|
+
* - `"json"` — stable JSON **text** with sorted keys.
|
|
169
|
+
* - `"pretty"` — human-readable plaintext (optionally colorized; see
|
|
170
|
+
* `colorize` / `indent` / `logger` / `includeEdges` / `includeSubgraphs`).
|
|
171
|
+
* - `"mermaid"` — Mermaid flowchart text.
|
|
172
|
+
* - `"d2"` — D2 diagram text.
|
|
173
|
+
*/
|
|
174
|
+
format?: "spec" | "json" | "pretty" | "mermaid" | "d2";
|
|
175
|
+
/** Pretty/diagram render: direction for diagram formats (default `LR`). */
|
|
176
|
+
direction?: GraphDiagramDirection;
|
|
177
|
+
/** Pretty/JSON render: indent (default 2 for JSON, ignored for pretty). */
|
|
178
|
+
indent?: number;
|
|
179
|
+
/** Pretty render: optional logger hook; fires with the rendered text before return. */
|
|
180
|
+
logger?: (text: string) => void;
|
|
181
|
+
/** Pretty render: include an Edges section (default `true`). */
|
|
182
|
+
includeEdges?: boolean;
|
|
183
|
+
/** Pretty render: include a Subgraphs section (default `true`). */
|
|
184
|
+
includeSubgraphs?: boolean;
|
|
185
|
+
};
|
|
186
|
+
/** JSON snapshot from {@link Graph.describe} (GRAPHREFLY-SPEC §3.6, Appendix B). */
|
|
187
|
+
type GraphDescribeOutput = {
|
|
188
|
+
name: string;
|
|
189
|
+
nodes: Record<string, DescribeNodeOutput>;
|
|
190
|
+
edges: ReadonlyArray<{
|
|
191
|
+
from: string;
|
|
192
|
+
to: string;
|
|
193
|
+
}>;
|
|
194
|
+
subgraphs: string[];
|
|
195
|
+
/**
|
|
196
|
+
* Re-read the live graph with higher detail (Phase 3.3b).
|
|
197
|
+
* Returns a new `GraphDescribeOutput`; the original remains a snapshot.
|
|
198
|
+
* Present on live describe results; absent on deserialized snapshots.
|
|
199
|
+
*/
|
|
200
|
+
expand?: (detailOrFields: DescribeDetail | DescribeField[]) => GraphDescribeOutput;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Persisted graph snapshot: {@link GraphDescribeOutput} plus optional format version
|
|
204
|
+
* ({@link Graph.snapshot}, {@link Graph.restore}, {@link Graph.fromSnapshot}, {@link Graph.toObject},
|
|
205
|
+
* {@link Graph.toJSONString} — §3.8).
|
|
206
|
+
*/
|
|
207
|
+
type GraphPersistSnapshot = GraphDescribeOutput & {
|
|
208
|
+
version?: number;
|
|
209
|
+
};
|
|
210
|
+
type GraphFactoryContext = {
|
|
211
|
+
path: string;
|
|
212
|
+
type: DescribeNodeOutput["type"];
|
|
213
|
+
value: unknown;
|
|
214
|
+
meta: Record<string, unknown>;
|
|
215
|
+
deps: readonly string[];
|
|
216
|
+
resolvedDeps: readonly Node[];
|
|
217
|
+
};
|
|
218
|
+
type GraphNodeFactory = (name: string, context: GraphFactoryContext) => Node;
|
|
219
|
+
/**
|
|
220
|
+
* Checkpoint record shape passed to `StorageTier.save`. Written by
|
|
221
|
+
* {@link Graph.attachStorage} per-tier according to each tier's
|
|
222
|
+
* `compactEvery` cadence.
|
|
223
|
+
*
|
|
224
|
+
* `mode: "full"` → full snapshot. Baseline anchor emitted on the first save
|
|
225
|
+
* and every `compactEvery`-th save thereafter. Sufficient to recover state
|
|
226
|
+
* on its own without WAL replay.
|
|
227
|
+
* `mode: "diff"` → delta payload only, relative to this tier's most recent
|
|
228
|
+
* `"full"` baseline. Between compacts. Wire-efficient; requires WAL replay
|
|
229
|
+
* over the preceding `"full"` record to reconstruct state.
|
|
230
|
+
*
|
|
231
|
+
* Every record includes `seq` (per-tier monotonic counter), `timestamp_ns`
|
|
232
|
+
* (wall-clock at flush time), and `format_version` (envelope version for
|
|
233
|
+
* cross-version WAL replay).
|
|
234
|
+
*/
|
|
235
|
+
type GraphCheckpointRecord = {
|
|
236
|
+
seq: number;
|
|
237
|
+
timestamp_ns: number;
|
|
238
|
+
format_version: number;
|
|
239
|
+
} & ({
|
|
240
|
+
mode: "full";
|
|
241
|
+
snapshot: GraphPersistSnapshot;
|
|
242
|
+
} | {
|
|
243
|
+
mode: "diff";
|
|
244
|
+
diff: GraphWALDiff;
|
|
245
|
+
});
|
|
246
|
+
/** Options for {@link Graph.attachStorage}. */
|
|
247
|
+
type GraphAttachStorageOptions = {
|
|
248
|
+
/**
|
|
249
|
+
* Before the first save, attempt to restore from the first tier whose
|
|
250
|
+
* `load(graph.name)` hits. Runs asynchronously in the background for
|
|
251
|
+
* async tiers; errors surface via `onError`. Default `false`.
|
|
252
|
+
*/
|
|
253
|
+
autoRestore?: boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Limit the subscription surface (scoped observe). By default
|
|
256
|
+
* `attachStorage` observes every node in the graph tree; on large graphs
|
|
257
|
+
* that's thousands of subscriptions just for tier-gating. Pass a path
|
|
258
|
+
* list (or a single glob) to observe only those nodes.
|
|
259
|
+
*/
|
|
260
|
+
paths?: readonly string[] | string;
|
|
261
|
+
/** Pre-save path-level filter — skip records triggered by paths that fail this predicate. */
|
|
262
|
+
filter?: (name: string, described: DescribeNodeOutput) => boolean;
|
|
263
|
+
/** Surfaced on tier save errors and autoRestore failures. */
|
|
264
|
+
onError?: (error: unknown, tier: StorageTier) => void;
|
|
265
|
+
};
|
|
266
|
+
/** Direction options for diagram export helpers. */
|
|
267
|
+
type GraphDiagramDirection = "TD" | "LR" | "BT" | "RL";
|
|
268
|
+
/** Options for {@link Graph.toMermaid} / {@link Graph.toD2}. */
|
|
269
|
+
type GraphDiagramOptions = {
|
|
270
|
+
/**
|
|
271
|
+
* Diagram flow direction.
|
|
272
|
+
* - `TD`: top-down
|
|
273
|
+
* - `LR`: left-right (default)
|
|
274
|
+
* - `BT`: bottom-top
|
|
275
|
+
* - `RL`: right-left
|
|
276
|
+
*/
|
|
277
|
+
direction?: GraphDiagramDirection;
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* Option shapes that trigger structured-mode dispatch in {@link Graph.observe}.
|
|
281
|
+
* Presence of any of these fields (truthy) → returns {@link ObserveResult};
|
|
282
|
+
* otherwise `observe()` returns the raw-stream variants.
|
|
283
|
+
*/
|
|
284
|
+
type StructuredTriggers = {
|
|
285
|
+
structured?: true;
|
|
286
|
+
timeline?: true;
|
|
287
|
+
causal?: true;
|
|
288
|
+
derived?: true;
|
|
289
|
+
format?: "pretty" | "json";
|
|
290
|
+
detail?: "minimal" | "full";
|
|
291
|
+
};
|
|
292
|
+
/** {@link Graph.observe} on a single node or meta path — sink receives plain message batches. */
|
|
293
|
+
type GraphObserveOne = {
|
|
294
|
+
subscribe(sink: NodeSink): () => void;
|
|
295
|
+
/** Send messages upstream toward the observed node's sources (e.g. PAUSE/RESUME). */
|
|
296
|
+
up(messages: Messages): void;
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* {@link Graph.observe} on the whole graph — sink receives each batch with the qualified source path.
|
|
300
|
+
* Subscription order follows code-point sort on paths (mounts-first walk, then sorted locals/meta).
|
|
301
|
+
*/
|
|
302
|
+
type GraphObserveAll = {
|
|
303
|
+
subscribe(sink: (nodePath: string, messages: Messages) => void): () => void;
|
|
304
|
+
/** Send messages upstream toward a specific observed node's sources (e.g. PAUSE/RESUME). */
|
|
305
|
+
up(path: string, messages: Messages): void;
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* Detail level for `observe()` progressive disclosure (Phase 3.3b).
|
|
309
|
+
* - `"minimal"` — DATA events only, no timestamps, no causal info.
|
|
310
|
+
* - `"standard"` — all message types (DATA, DIRTY, RESOLVED, INVALIDATE,
|
|
311
|
+
* PAUSE, RESUME, COMPLETE, ERROR, TEARDOWN).
|
|
312
|
+
* - `"full"` — standard + timeline + causal + derived.
|
|
313
|
+
*/
|
|
314
|
+
type ObserveDetail = "minimal" | "standard" | "full";
|
|
315
|
+
/** Options for structured observation modes on {@link Graph.observe}. */
|
|
316
|
+
type ObserveOptions = {
|
|
317
|
+
actor?: Actor;
|
|
318
|
+
/** Return an {@link ObserveResult} accumulator instead of a raw stream. */
|
|
319
|
+
structured?: boolean;
|
|
320
|
+
/** Include causal trace info (which dep triggered each recomputation). */
|
|
321
|
+
causal?: boolean;
|
|
322
|
+
/** Include timestamps and batch context on each event. */
|
|
323
|
+
timeline?: boolean;
|
|
324
|
+
/** Include per-evaluation dep snapshots for compute/derived nodes. */
|
|
325
|
+
derived?: boolean;
|
|
326
|
+
/**
|
|
327
|
+
* Detail level (Phase 3.3b). Individual flags (`causal`, `timeline`, `derived`)
|
|
328
|
+
* override. `"full"` implies all three plus structured.
|
|
329
|
+
* `"minimal"` filters to DATA-only events.
|
|
330
|
+
*/
|
|
331
|
+
detail?: ObserveDetail;
|
|
332
|
+
/**
|
|
333
|
+
* When set, auto-enables structured mode and attaches a logger.
|
|
334
|
+
* `"pretty"` renders colored one-line output; `"json"` emits one JSON object per event.
|
|
335
|
+
*/
|
|
336
|
+
format?: "pretty" | "json";
|
|
337
|
+
/** Sink for rendered lines (`console.log` by default). Only used when `format` is set. */
|
|
338
|
+
logger?: (line: string, event: ObserveEvent) => void;
|
|
339
|
+
/** Keep only these event types in formatted output. Only used when `format` is set. */
|
|
340
|
+
includeTypes?: ObserveEvent["type"][];
|
|
341
|
+
/** Exclude these event types from formatted output. Only used when `format` is set. */
|
|
342
|
+
excludeTypes?: ObserveEvent["type"][];
|
|
343
|
+
/** Built-in color preset (`ansi` default) or explicit color tokens. Only used when `format` is set. */
|
|
344
|
+
theme?: ObserveThemeName | ObserveTheme;
|
|
345
|
+
/**
|
|
346
|
+
* Cap the `events` buffer. When set, the result uses a {@link RingBuffer}
|
|
347
|
+
* under the hood: oldest events are dropped on overflow. Unbounded when
|
|
348
|
+
* omitted (default).
|
|
349
|
+
*/
|
|
350
|
+
maxEvents?: number;
|
|
351
|
+
};
|
|
352
|
+
/** Accumulated observation result (structured mode). */
|
|
353
|
+
type ObserveResult<T = unknown> = AsyncIterable<ObserveEvent> & {
|
|
354
|
+
/** Latest DATA value by observed path. */
|
|
355
|
+
readonly values: Record<string, T>;
|
|
356
|
+
/** Number of DIRTY messages received. */
|
|
357
|
+
readonly dirtyCount: number;
|
|
358
|
+
/** Number of RESOLVED messages received. */
|
|
359
|
+
readonly resolvedCount: number;
|
|
360
|
+
/** Number of INVALIDATE messages received (tier 1 cache-clear). */
|
|
361
|
+
readonly invalidateCount: number;
|
|
362
|
+
/** Number of PAUSE messages received (tier 2 backpressure). */
|
|
363
|
+
readonly pauseCount: number;
|
|
364
|
+
/** Number of RESUME messages received (tier 2 backpressure). */
|
|
365
|
+
readonly resumeCount: number;
|
|
366
|
+
/** Number of TEARDOWN messages received (tier 5 permanent cleanup). */
|
|
367
|
+
readonly teardownCount: number;
|
|
368
|
+
/**
|
|
369
|
+
* All events in order — ring-buffered when `options.maxEvents` is set,
|
|
370
|
+
* unbounded otherwise. Always materialized as an `ObserveEvent[]`
|
|
371
|
+
* snapshot on read.
|
|
372
|
+
*/
|
|
373
|
+
readonly events: ObserveEvent[];
|
|
374
|
+
/** True if any observed node sent COMPLETE without prior ERROR on that node. */
|
|
375
|
+
readonly anyCompletedCleanly: boolean;
|
|
376
|
+
/** True if any observed node sent ERROR. */
|
|
377
|
+
readonly anyErrored: boolean;
|
|
378
|
+
/** True if at least one COMPLETE received and no ERROR from any observed node. */
|
|
379
|
+
readonly completedWithoutErrors: boolean;
|
|
380
|
+
/**
|
|
381
|
+
* Attach a live listener that fires for each event as it arrives.
|
|
382
|
+
* Returns an unsubscribe fn. Independent of the `events` buffer.
|
|
383
|
+
*/
|
|
384
|
+
onEvent(listener: (event: ObserveEvent) => void): () => void;
|
|
385
|
+
/** Stop observing. */
|
|
386
|
+
dispose(): void;
|
|
387
|
+
/**
|
|
388
|
+
* Resubscribe with higher detail (Phase 3.3b).
|
|
389
|
+
* Disposes current observation, returns new `ObserveResult` with merged options.
|
|
390
|
+
*/
|
|
391
|
+
expand(extra: Partial<Pick<ObserveOptions, "causal" | "timeline" | "derived">> | ObserveDetail): ObserveResult<T>;
|
|
392
|
+
};
|
|
393
|
+
/** Fields common to every {@link ObserveEvent} variant. */
|
|
394
|
+
interface ObserveEventBase {
|
|
395
|
+
path?: string;
|
|
396
|
+
/** Optional `timeline` context — wall-clock when `options.timeline === true`. */
|
|
397
|
+
timestamp_ns?: number;
|
|
398
|
+
in_batch?: boolean;
|
|
399
|
+
/** Monotonically increasing counter per subscribe-callback invocation. All events in one delivery share the same id. */
|
|
400
|
+
batch_id?: number;
|
|
401
|
+
}
|
|
402
|
+
/** Optional `causal` context present on `data`/`resolved`/`derived` events. */
|
|
403
|
+
interface ObserveCausalContext {
|
|
404
|
+
trigger_dep_index?: number;
|
|
405
|
+
trigger_dep_name?: string;
|
|
406
|
+
/**
|
|
407
|
+
* V0 version of the triggering dep at observation time (§6.0b).
|
|
408
|
+
* This is the dep's post-emission version (after its own `advanceVersion`),
|
|
409
|
+
* not the pre-emission version that caused this node's recomputation.
|
|
410
|
+
*/
|
|
411
|
+
trigger_version?: {
|
|
412
|
+
id: string;
|
|
413
|
+
version: number;
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* One scalar per dep: the last value that arrived in the current wave,
|
|
417
|
+
* or the pre-wave cached value for deps that didn't fire. Convenient
|
|
418
|
+
* for single-value-wave tooling (the common case).
|
|
419
|
+
*/
|
|
420
|
+
dep_values?: unknown[];
|
|
421
|
+
/**
|
|
422
|
+
* Full per-dep batches for the wave that fired the fn — `dep_batches[i]`
|
|
423
|
+
* is the array of values dep `i` delivered this wave (`undefined` for
|
|
424
|
+
* deps that didn't fire). Use this to distinguish a single-value wave
|
|
425
|
+
* from a multi-value wave; `dep_values` compresses each batch to its
|
|
426
|
+
* last element and hides that difference.
|
|
427
|
+
*/
|
|
428
|
+
dep_batches?: ReadonlyArray<ReadonlyArray<unknown> | undefined>;
|
|
429
|
+
}
|
|
430
|
+
/** A single event in the structured observation log (discriminated on `type`). */
|
|
431
|
+
type ObserveEvent = (ObserveEventBase & ObserveCausalContext & {
|
|
432
|
+
type: "data";
|
|
433
|
+
data: unknown;
|
|
434
|
+
}) | (ObserveEventBase & {
|
|
435
|
+
type: "dirty";
|
|
436
|
+
}) | (ObserveEventBase & ObserveCausalContext & {
|
|
437
|
+
type: "resolved";
|
|
438
|
+
}) | (ObserveEventBase & {
|
|
439
|
+
type: "invalidate";
|
|
440
|
+
}) | (ObserveEventBase & {
|
|
441
|
+
type: "pause";
|
|
442
|
+
lockId: unknown;
|
|
443
|
+
}) | (ObserveEventBase & {
|
|
444
|
+
type: "resume";
|
|
445
|
+
lockId: unknown;
|
|
446
|
+
}) | (ObserveEventBase & {
|
|
447
|
+
type: "complete";
|
|
448
|
+
}) | (ObserveEventBase & {
|
|
449
|
+
type: "error";
|
|
450
|
+
data: unknown;
|
|
451
|
+
}) | (ObserveEventBase & {
|
|
452
|
+
type: "teardown";
|
|
453
|
+
}) | (ObserveEventBase & ObserveCausalContext & {
|
|
454
|
+
type: "derived";
|
|
455
|
+
dep_values: unknown[];
|
|
456
|
+
});
|
|
457
|
+
/** Built-in color preset names for observe `format` rendering. */
|
|
458
|
+
type ObserveThemeName = "none" | "ansi";
|
|
459
|
+
/** ANSI/style overrides for observe `format` event rendering. */
|
|
460
|
+
type ObserveTheme = Partial<Record<ObserveEvent["type"] | "path" | "reset", string>>;
|
|
461
|
+
/**
|
|
462
|
+
* Named container for nodes and explicit edges (GRAPHREFLY-SPEC §3.1–§3.7).
|
|
463
|
+
*
|
|
464
|
+
* Qualified paths use `::` as the segment separator (for example `parent::child::node`).
|
|
465
|
+
*
|
|
466
|
+
* Edges are pure wires: `connect` only validates wiring — the target must already list the source in
|
|
467
|
+
* its dependency array; no transforms run on the edge.
|
|
468
|
+
*
|
|
469
|
+
* @example
|
|
470
|
+
* ```ts
|
|
471
|
+
* import { Graph, state } from "@graphrefly/graphrefly-ts";
|
|
472
|
+
*
|
|
473
|
+
* const g = new Graph("app");
|
|
474
|
+
* g.add("counter", state(0));
|
|
475
|
+
* ```
|
|
476
|
+
*
|
|
477
|
+
* @category graph
|
|
478
|
+
*/
|
|
479
|
+
declare class Graph {
|
|
480
|
+
readonly name: string;
|
|
481
|
+
readonly opts: Readonly<GraphOptions>;
|
|
482
|
+
/** Protocol config bound to this graph (defaults to `defaultConfig`). */
|
|
483
|
+
readonly config: GraphReFlyConfig;
|
|
484
|
+
/** @internal — exposed for {@link teardownMountedGraph} and cross-graph helpers. */
|
|
485
|
+
readonly _nodes: Map<string, Node<unknown>>;
|
|
486
|
+
/**
|
|
487
|
+
* @internal Reverse lookup for duplicate-instance detection in
|
|
488
|
+
* {@link Graph.add} — O(1) replacement for an O(n) scan of `_nodes`.
|
|
489
|
+
* Weak so nodes can be GC'd after `remove()` even if a caller keeps the
|
|
490
|
+
* map alive via some unusual pattern.
|
|
491
|
+
*/
|
|
492
|
+
private readonly _nodeToName;
|
|
493
|
+
/** @internal — exposed for {@link teardownMountedGraph}. */
|
|
494
|
+
readonly _mounts: Map<string, Graph>;
|
|
495
|
+
/**
|
|
496
|
+
* @internal Parent graph if this instance is mounted. `undefined` when
|
|
497
|
+
* this is the root or when the graph has been unmounted. Used for
|
|
498
|
+
* reparenting rejection + O(depth) ancestor walks.
|
|
499
|
+
*/
|
|
500
|
+
_parent: Graph | undefined;
|
|
501
|
+
private readonly _storageDisposers;
|
|
502
|
+
private readonly _disposers;
|
|
503
|
+
/**
|
|
504
|
+
* @param name - Non-empty graph id (must not contain `::` and must not
|
|
505
|
+
* equal the reserved meta segment `__meta__`).
|
|
506
|
+
* @param opts - See {@link GraphOptions}. Stored frozen on the instance.
|
|
507
|
+
*/
|
|
508
|
+
constructor(name: string, opts?: GraphOptions);
|
|
509
|
+
/**
|
|
510
|
+
* Walk ancestors up through `_parent`. Returns the chain starting at this
|
|
511
|
+
* instance, ending at the root (a graph with no parent). O(depth).
|
|
512
|
+
*
|
|
513
|
+
* @param includeSelf - Include `this` in the chain (default `true`).
|
|
514
|
+
*/
|
|
515
|
+
ancestors(includeSelf?: boolean): Graph[];
|
|
516
|
+
/**
|
|
517
|
+
* Registers a node under a local name. Fails if the name is already used,
|
|
518
|
+
* reserved by a mount, the same node instance is already registered, or
|
|
519
|
+
* the node is torn down.
|
|
520
|
+
*
|
|
521
|
+
* Returns the registered node so callers can chain:
|
|
522
|
+
* `const counter = g.add("counter", state(0))`.
|
|
523
|
+
*
|
|
524
|
+
* @param name - Local key (no `::`).
|
|
525
|
+
* @param node - Node instance to own.
|
|
526
|
+
*/
|
|
527
|
+
add<T extends Node>(name: string, node: T): T;
|
|
528
|
+
/**
|
|
529
|
+
* Bulk-apply a minimum versioning level to every currently-registered node
|
|
530
|
+
* in this graph (roadmap §6.0). `_applyVersioning` is monotonic — nodes
|
|
531
|
+
* already at a higher level are untouched. The method refuses to run
|
|
532
|
+
* mid-wave; invoke at setup time before any external subscribers attach.
|
|
533
|
+
*
|
|
534
|
+
* **Not** a default-for-future-adds mechanism — that's what
|
|
535
|
+
* `config.defaultVersioning` is for. Nodes added after this call do NOT
|
|
536
|
+
* automatically inherit `level`; register new nodes with their own
|
|
537
|
+
* `opts.versioning` or set `config.defaultVersioning` before construction.
|
|
538
|
+
*
|
|
539
|
+
* **Scope:** local only. Does not propagate to mounted subgraphs.
|
|
540
|
+
*
|
|
541
|
+
* @param level - `0` for V0, `1` for V1, or `undefined` to no-op.
|
|
542
|
+
*/
|
|
543
|
+
setVersioning(level: VersioningLevel | undefined): void;
|
|
544
|
+
/**
|
|
545
|
+
* Unregisters a node or unmounts a subgraph and sends `[[TEARDOWN]]` to the
|
|
546
|
+
* removed node or recursively through the mounted subtree (§3.2).
|
|
547
|
+
*
|
|
548
|
+
* @param name - Local mount or node name.
|
|
549
|
+
* @returns Audit record of what was removed: `{kind, nodes, mounts}`.
|
|
550
|
+
* `kind: "node"` → `nodes: [name]`, `mounts: []`. `kind: "mount"` →
|
|
551
|
+
* `nodes` lists every primary node torn down across the subtree (sorted
|
|
552
|
+
* qualified paths relative to the unmounted subgraph) and `mounts` lists
|
|
553
|
+
* the mounted subgraphs in depth-first order including `name` itself.
|
|
554
|
+
*/
|
|
555
|
+
remove(name: string): GraphRemoveAudit;
|
|
556
|
+
/**
|
|
557
|
+
* Bulk remove — invokes {@link Graph.remove} for every local name matching
|
|
558
|
+
* `filter`. Audit records merge into a single result. Mounted subgraphs
|
|
559
|
+
* are included via `filter` receiving the mount name; internal subtree
|
|
560
|
+
* entries are not walked directly (use describe + scan for tree-level
|
|
561
|
+
* queries).
|
|
562
|
+
*
|
|
563
|
+
* @param filter - Predicate or glob. Glob strings support `*` within a
|
|
564
|
+
* segment and `**` across segments (same grammar as `restore({only})`).
|
|
565
|
+
* @returns Combined audit of all nodes + mounts removed.
|
|
566
|
+
*/
|
|
567
|
+
removeAll(filter: ((name: string) => boolean) | string): GraphRemoveAudit;
|
|
568
|
+
/**
|
|
569
|
+
* Iterable over locally-registered `[localName, Node]` pairs (sorted).
|
|
570
|
+
* Does not recurse into mounts.
|
|
571
|
+
*/
|
|
572
|
+
[Symbol.iterator](): IterableIterator<[string, Node]>;
|
|
573
|
+
/**
|
|
574
|
+
* Returns a node by local name or `::` qualified path.
|
|
575
|
+
* Local names are looked up directly; paths with `::` delegate to {@link resolve}.
|
|
576
|
+
*
|
|
577
|
+
* @param name - Local name or qualified path.
|
|
578
|
+
*/
|
|
579
|
+
node(name: string): Node;
|
|
580
|
+
/**
|
|
581
|
+
* Reads `graph.node(name).get()` — accepts `::` qualified paths (§3.2).
|
|
582
|
+
*
|
|
583
|
+
* @param name - Local name or qualified path.
|
|
584
|
+
* @returns Cached value or `undefined`.
|
|
585
|
+
*/
|
|
586
|
+
get(name: string): unknown;
|
|
587
|
+
/**
|
|
588
|
+
* Shorthand for `graph.node(name).down([[DATA, value]], { actor })` — accepts `::` qualified paths (§3.2).
|
|
589
|
+
*
|
|
590
|
+
* @param name - Local name or qualified path.
|
|
591
|
+
* @param value - Next `DATA` payload.
|
|
592
|
+
* @param options - Optional `actor` and `internal` guard bypass.
|
|
593
|
+
*/
|
|
594
|
+
set(name: string, value: unknown, options?: GraphActorOptions): void;
|
|
595
|
+
/**
|
|
596
|
+
* Atomic multi-node DATA write. Wraps every {@link Graph.set} call in a
|
|
597
|
+
* single `batch(...)` so downstream dependents see one coalesced wave
|
|
598
|
+
* instead of N cascading ones.
|
|
599
|
+
*
|
|
600
|
+
* @param entries - `{name → value}` map or `[name, value]` pairs.
|
|
601
|
+
* @param options - Passed to each underlying `set` call (same `actor` + `internal` semantics).
|
|
602
|
+
*/
|
|
603
|
+
setAll(entries: Record<string, unknown> | Iterable<readonly [string, unknown]>, options?: GraphActorOptions): void;
|
|
604
|
+
/**
|
|
605
|
+
* Emit a single `[[INVALIDATE]]` (tier 1) on a node. Thin wrapper over
|
|
606
|
+
* `node.down([[INVALIDATE]], …)` matching the {@link Graph.set} ergonomics.
|
|
607
|
+
*/
|
|
608
|
+
invalidate(name: string, options?: GraphActorOptions): void;
|
|
609
|
+
/**
|
|
610
|
+
* Emit a single `[[ERROR, err]]` (tier 4) on a node.
|
|
611
|
+
*/
|
|
612
|
+
error(name: string, err: unknown, options?: GraphActorOptions): void;
|
|
613
|
+
/**
|
|
614
|
+
* Emit a single `[[COMPLETE]]` (tier 4) on a node, declaring the stream
|
|
615
|
+
* cleanly finished. Distinct from {@link Graph.remove} (which emits
|
|
616
|
+
* TEARDOWN and unregisters the node).
|
|
617
|
+
*/
|
|
618
|
+
complete(name: string, options?: GraphActorOptions): void;
|
|
619
|
+
/**
|
|
620
|
+
* Returns the full edge list for this graph tree, derived on demand from
|
|
621
|
+
* each registered node's `_deps` (no stored registry). Local-only
|
|
622
|
+
* (non-recursive) by default to match the historical `edges()` surface;
|
|
623
|
+
* pass `{recursive: true}` to include mounted subgraphs with qualified
|
|
624
|
+
* paths relative to this graph.
|
|
625
|
+
*
|
|
626
|
+
* Use {@link Graph.describe} for full-tree snapshots with edges already
|
|
627
|
+
* qualified and paired with node metadata.
|
|
628
|
+
*/
|
|
629
|
+
edges(opts?: {
|
|
630
|
+
recursive?: boolean;
|
|
631
|
+
}): ReadonlyArray<[string, string]>;
|
|
632
|
+
/**
|
|
633
|
+
* Embed a child graph at a local mount name (§3.4). Child nodes are reachable via
|
|
634
|
+
* {@link Graph.resolve} using `::` delimited paths (§3.5). Lifecycle
|
|
635
|
+
* {@link Graph.signal} visits mounted subgraphs recursively.
|
|
636
|
+
*
|
|
637
|
+
* Rejects: same name as existing node or mount, self-mount, mount cycles,
|
|
638
|
+
* and the same child graph instance mounted twice on one parent.
|
|
639
|
+
*
|
|
640
|
+
* @param name - Local mount point.
|
|
641
|
+
* @param child - Nested `Graph` instance.
|
|
642
|
+
* @returns The mounted `child`, for chaining.
|
|
643
|
+
*/
|
|
644
|
+
mount<G extends Graph>(name: string, child: G): G;
|
|
645
|
+
/**
|
|
646
|
+
* Look up a node by qualified path (§3.5). Segments are separated by `::`.
|
|
647
|
+
*
|
|
648
|
+
* If the first segment equals this graph's {@link Graph.name}, it is stripped
|
|
649
|
+
* (so `root.resolve("app::a")` works when `root.name === "app"`). The strip
|
|
650
|
+
* is applied **recursively** when descending into mounted children, so
|
|
651
|
+
* `child.resolve("child::x")` also works when `child.name === "child"`.
|
|
652
|
+
*
|
|
653
|
+
* @param path - Qualified `::` path or local name.
|
|
654
|
+
* @returns The resolved `Node`.
|
|
655
|
+
*/
|
|
656
|
+
resolve(path: string): Node;
|
|
657
|
+
/**
|
|
658
|
+
* Non-throwing {@link Graph.resolve}. Returns `undefined` instead of
|
|
659
|
+
* throwing when the path does not resolve to a node.
|
|
660
|
+
*/
|
|
661
|
+
tryResolve(path: string): Node | undefined;
|
|
662
|
+
private _resolveFromSegments;
|
|
663
|
+
/**
|
|
664
|
+
* Resolve `::__meta__::key` segments from a registered primary node (possibly chained).
|
|
665
|
+
*/
|
|
666
|
+
private _resolveMetaChainFromNode;
|
|
667
|
+
/**
|
|
668
|
+
* Deliver a message batch to every registered node in this graph and, recursively,
|
|
669
|
+
* in mounted child graphs (§3.7). Recurses into mounts first, then delivers to
|
|
670
|
+
* local nodes (sorted by name). Each {@link Node} receives at most one delivery
|
|
671
|
+
* per call (deduped by reference).
|
|
672
|
+
*
|
|
673
|
+
* **Primary-vs-meta filter asymmetry (intentional):** primary nodes receive the
|
|
674
|
+
* unfiltered `messages` batch — that's the canonical data-plane flow. Companion
|
|
675
|
+
* `meta` nodes receive a filtered subset keyed by the per-type `metaPassthrough`
|
|
676
|
+
* flag on {@link GraphReFlyConfig}. Built-in defaults: PAUSE / RESUME / DATA /
|
|
677
|
+
* RESOLVED pass through to meta; INVALIDATE / COMPLETE / ERROR / TEARDOWN do
|
|
678
|
+
* not.
|
|
679
|
+
*
|
|
680
|
+
* **Where lifecycle terminals reach meta:**
|
|
681
|
+
* - **TEARDOWN** — primary's `_emit` cascades to meta children directly (see
|
|
682
|
+
* `core/node.ts` "Meta TEARDOWN fan-out" block) so meta is torn down with
|
|
683
|
+
* its primary regardless of the signal-level filter.
|
|
684
|
+
* - **COMPLETE / ERROR / INVALIDATE** — scoped to primaries on the broadcast
|
|
685
|
+
* path. Meta companions are an attribution side-channel, not a lifecycle
|
|
686
|
+
* participant; address meta directly via `meta.down(...)` if you need to
|
|
687
|
+
* forward these. Audit confirmed 2026-04-17: no current meta consumer
|
|
688
|
+
* relies on broadcast COMPLETE/ERROR/INVALIDATE delivery.
|
|
689
|
+
*
|
|
690
|
+
* @param messages - Batch to deliver to every registered node (and mounts, recursively).
|
|
691
|
+
* @param options - Optional `actor` / `internal` for transport.
|
|
692
|
+
*/
|
|
693
|
+
signal(messages: Messages, options?: GraphActorOptions): void;
|
|
694
|
+
private _signalDeliver;
|
|
695
|
+
private _signalMetaSubtree;
|
|
696
|
+
/**
|
|
697
|
+
* Static structure snapshot: qualified node keys, edges, mount names (GRAPHREFLY-SPEC §3.6, Appendix B).
|
|
698
|
+
*
|
|
699
|
+
* `format` controls the return type:
|
|
700
|
+
* - omitted or `"spec"` → {@link GraphDescribeOutput} object.
|
|
701
|
+
* - `"json"` / `"pretty"` / `"mermaid"` / `"d2"` → rendered string.
|
|
702
|
+
*
|
|
703
|
+
* @param options - Optional `actor` for guard-scoped visibility, `filter` for
|
|
704
|
+
* selective output, or `format` to render.
|
|
705
|
+
*
|
|
706
|
+
* @example
|
|
707
|
+
* ```ts
|
|
708
|
+
* graph.describe() // full snapshot object
|
|
709
|
+
* graph.describe({ filter: { status: "errored" } }) // filtered object
|
|
710
|
+
* graph.describe({ format: "pretty" }) // human-readable text
|
|
711
|
+
* graph.describe({ format: "mermaid" }) // Mermaid flowchart
|
|
712
|
+
* graph.describe({ format: "d2", direction: "TD" }) // D2 top-down
|
|
713
|
+
* ```
|
|
714
|
+
*/
|
|
715
|
+
describe(options: GraphDescribeOptions & {
|
|
716
|
+
format: "json" | "pretty" | "mermaid" | "d2";
|
|
717
|
+
}): string;
|
|
718
|
+
describe(options?: GraphDescribeOptions): GraphDescribeOutput;
|
|
719
|
+
private _collectSubgraphs;
|
|
720
|
+
/**
|
|
721
|
+
* Snapshot-based resource profile: per-node stats, orphan effect detection,
|
|
722
|
+
* memory hotspots. Zero runtime overhead — walks nodes on demand.
|
|
723
|
+
*
|
|
724
|
+
* @param opts - Optional `topN` for hotspot limit (default 10).
|
|
725
|
+
* @returns Aggregate profile with per-node details, hotspots, and orphan effects.
|
|
726
|
+
*/
|
|
727
|
+
resourceProfile(opts?: GraphProfileOptions): GraphProfileResult;
|
|
728
|
+
/**
|
|
729
|
+
* Reachability query rooted at `from`. Instance convenience — wraps
|
|
730
|
+
* `reachable(this.describe(), from, direction, opts)`. See
|
|
731
|
+
* {@link reachable} for semantics.
|
|
732
|
+
*/
|
|
733
|
+
reachable(from: string, direction: ReachableDirection, opts: ReachableOptions & {
|
|
734
|
+
withDetail: true;
|
|
735
|
+
}): ReachableResult;
|
|
736
|
+
reachable(from: string, direction: ReachableDirection, opts?: ReachableOptions): string[];
|
|
737
|
+
/**
|
|
738
|
+
* @internal Collect all qualified paths in this graph tree matching a
|
|
739
|
+
* glob pattern. Used by scoped autoCheckpoint subscription.
|
|
740
|
+
*/
|
|
741
|
+
private _pathsMatching;
|
|
742
|
+
private _collectObserveTargets;
|
|
743
|
+
private _appendMetaObserveTargets;
|
|
744
|
+
/**
|
|
745
|
+
* Live message stream from one node (or meta path), or from the whole graph (§3.6).
|
|
746
|
+
*
|
|
747
|
+
* Two modes dispatched on first argument:
|
|
748
|
+
* - `observe(path, options?)` — one node. Returns {@link GraphObserveOne}
|
|
749
|
+
* (raw stream), or {@link ObserveResult} when `options` requests structured
|
|
750
|
+
* accumulation (`structured`, `timeline`, `causal`, `derived`, `format`,
|
|
751
|
+
* `detail: "minimal"|"full"`).
|
|
752
|
+
* - `observe(options?)` — all nodes. Returns {@link GraphObserveAll} (raw),
|
|
753
|
+
* or {@link ObserveResult} under the same structured trigger conditions.
|
|
754
|
+
*
|
|
755
|
+
* Structured mode subscribes in sorted path order (code-point). Inspector
|
|
756
|
+
* extras (`causal`/`derived`) require `graph.config.inspectorEnabled`;
|
|
757
|
+
* when disabled, those fields silently drop and the rest still works.
|
|
758
|
+
*
|
|
759
|
+
* `ObserveResult` is also an `AsyncIterable<ObserveEvent>` — use
|
|
760
|
+
* `for await (const ev of result)` for pull-based consumption.
|
|
761
|
+
*/
|
|
762
|
+
observe(path: string, options?: ObserveOptions & StructuredTriggers): ObserveResult;
|
|
763
|
+
observe(path: string, options?: ObserveOptions): GraphObserveOne;
|
|
764
|
+
observe(options: ObserveOptions & StructuredTriggers): ObserveResult;
|
|
765
|
+
observe(options?: ObserveOptions): GraphObserveAll;
|
|
766
|
+
/** Dispatch helper — builds a unified observer + its expand closure. */
|
|
767
|
+
private _buildStructuredObserver;
|
|
768
|
+
/**
|
|
769
|
+
* Unified observer builder — replaces the four ex-creators
|
|
770
|
+
* (`_createObserveResult` / `...ForAll` / `_createFallback…`). Accepts a
|
|
771
|
+
* list of `[path, node]` targets (single-element for one-node observe,
|
|
772
|
+
* N-element for all-nodes). Inspector hooks attach per-target when
|
|
773
|
+
* `causal`/`derived` requested AND `config.inspectorEnabled`; otherwise
|
|
774
|
+
* those fields gracefully drop.
|
|
775
|
+
*
|
|
776
|
+
* Events flow through a `recordEvent()` helper so the format logger,
|
|
777
|
+
* ring-buffer, and async-iterable hooks all share one push path.
|
|
778
|
+
*/
|
|
779
|
+
private _createObserveResult;
|
|
780
|
+
/**
|
|
781
|
+
* Attach format-rendering logger to an ObserveResult by subscribing to its
|
|
782
|
+
* event stream (no monkey-patching). Renders each event per `format` and
|
|
783
|
+
* `theme`, filtered by `includeTypes` / `excludeTypes`.
|
|
784
|
+
*/
|
|
785
|
+
private _attachFormatLogger;
|
|
786
|
+
/**
|
|
787
|
+
* Register a cleanup function to be called on {@link Graph.destroy}.
|
|
788
|
+
*
|
|
789
|
+
* Factories use this to attach teardown logic for internal nodes, keepalive
|
|
790
|
+
* subscriptions, or other resources that are not registered on the graph and
|
|
791
|
+
* would otherwise leak on repeated create/destroy cycles.
|
|
792
|
+
*
|
|
793
|
+
* Returns a removal function — call it to unregister the disposer early.
|
|
794
|
+
*/
|
|
795
|
+
addDisposer(fn: () => void): () => void;
|
|
796
|
+
/**
|
|
797
|
+
* Drains disposers (registered via {@link addDisposer}), then sends `[[TEARDOWN]]` to all
|
|
798
|
+
* nodes and clears registries on this graph and every mounted subgraph (§3.7).
|
|
799
|
+
* The instance is left empty and may be reused with {@link Graph.add}.
|
|
800
|
+
*/
|
|
801
|
+
destroy(): void;
|
|
802
|
+
/** Clear structure after parent already signaled TEARDOWN through this subtree. */
|
|
803
|
+
private _destroyClearOnly;
|
|
804
|
+
/**
|
|
805
|
+
* Serializes structure and current values to JSON-shaped data (§3.8). Same
|
|
806
|
+
* information as {@link Graph.describe} plus a `version` field for format
|
|
807
|
+
* evolution.
|
|
808
|
+
*
|
|
809
|
+
* The overload path supports three outputs:
|
|
810
|
+
* - no arg → `GraphPersistSnapshot` (plain JS object).
|
|
811
|
+
* - `{format: "json-string"}` → deterministic JSON `string`
|
|
812
|
+
* (key-sorted; safe for hashing or file write).
|
|
813
|
+
* - `{format: "bytes", codec: name}` → `Uint8Array` wrapped in the v1
|
|
814
|
+
* envelope from {@link encodeEnvelope}. The codec must be registered
|
|
815
|
+
* on this graph's {@link GraphReFlyConfig} via `config.registerCodec`.
|
|
816
|
+
* Paired with {@link Graph.decode} for auto-dispatch on the read side.
|
|
817
|
+
*/
|
|
818
|
+
snapshot(): GraphPersistSnapshot;
|
|
819
|
+
snapshot(opts: {
|
|
820
|
+
format: "json-string";
|
|
821
|
+
}): string;
|
|
822
|
+
snapshot(opts: {
|
|
823
|
+
format: "bytes";
|
|
824
|
+
codec: string;
|
|
825
|
+
}): Uint8Array;
|
|
826
|
+
/**
|
|
827
|
+
* Auto-dispatch a byte buffer produced by {@link Graph.snapshot} with
|
|
828
|
+
* `{format: "bytes", codec: name}`. Reads the v1 envelope, resolves the
|
|
829
|
+
* named codec on `config` (defaults to `defaultConfig`), and returns the
|
|
830
|
+
* decoded snapshot. Combine with {@link Graph.fromSnapshot} to rehydrate
|
|
831
|
+
* a full graph topology from bytes.
|
|
832
|
+
*
|
|
833
|
+
* @throws If the envelope is malformed or the named codec isn't
|
|
834
|
+
* registered on the target config.
|
|
835
|
+
*/
|
|
836
|
+
static decode(bytes: Uint8Array, opts?: {
|
|
837
|
+
config?: GraphReFlyConfig;
|
|
838
|
+
}): GraphPersistSnapshot;
|
|
839
|
+
/**
|
|
840
|
+
* Apply persisted values onto an existing graph whose topology matches the snapshot
|
|
841
|
+
* (§3.8). Only {@link DescribeNodeOutput.type} `state` entries with a `value` field
|
|
842
|
+
* are written by default; `derived` / `operator` / `effect` are always skipped so
|
|
843
|
+
* deps drive recomputation. `producer` entries are skipped unless `includeProducers`
|
|
844
|
+
* is set (producers recompute on activation, so restoring is usually a no-op
|
|
845
|
+
* overwritten on the next wave — opt in for audit / forensic round-trip use cases).
|
|
846
|
+
* Unknown paths are ignored.
|
|
847
|
+
*
|
|
848
|
+
* @param data - Snapshot envelope with matching `name` and node slices.
|
|
849
|
+
* @throws If `data.name` does not equal {@link Graph.name}.
|
|
850
|
+
*/
|
|
851
|
+
restore(data: GraphPersistSnapshot, options?: {
|
|
852
|
+
only?: string | readonly string[];
|
|
853
|
+
/**
|
|
854
|
+
* Fires per failing write. Default behavior (omitted) is silent —
|
|
855
|
+
* missing paths and guard denials are swallowed to match the
|
|
856
|
+
* historical semantics. Provide a callback to surface failures
|
|
857
|
+
* without aborting the remaining restores.
|
|
858
|
+
*/
|
|
859
|
+
onError?: (path: string, err: unknown) => void;
|
|
860
|
+
/**
|
|
861
|
+
* Restore `producer` node values alongside `state`. Default `false`:
|
|
862
|
+
* producers are reactive sources whose value recomputes on
|
|
863
|
+
* activation, so restoring from a snapshot is usually a no-op
|
|
864
|
+
* overwritten on the next wave. Audit / forensic round-trip use
|
|
865
|
+
* cases that need the stored value to survive restoration can
|
|
866
|
+
* opt in. Does not change `derived` / `effect` handling — those
|
|
867
|
+
* are always skipped.
|
|
868
|
+
*/
|
|
869
|
+
includeProducers?: boolean;
|
|
870
|
+
}): void;
|
|
871
|
+
/**
|
|
872
|
+
* Creates a graph named from the snapshot, optionally runs `build` to register nodes
|
|
873
|
+
* and mounts, then {@link Graph.restore} values (§3.8).
|
|
874
|
+
*
|
|
875
|
+
* @param data - Snapshot envelope (`version` checked).
|
|
876
|
+
* @param opts - Either a legacy `build(g)` callback, or an options object:
|
|
877
|
+
* - `build?` — topology constructor; skips auto-hydration when present.
|
|
878
|
+
* - `factories?` — map from glob pattern to {@link GraphNodeFactory},
|
|
879
|
+
* used by auto-hydration to reconstruct non-state nodes. Per-call (no
|
|
880
|
+
* process-global registry). First matching pattern wins.
|
|
881
|
+
* @returns Hydrated `Graph` instance.
|
|
882
|
+
*/
|
|
883
|
+
static fromSnapshot(data: GraphPersistSnapshot, opts?: ((g: Graph) => void) | {
|
|
884
|
+
build?: (g: Graph) => void;
|
|
885
|
+
factories?: Record<string, GraphNodeFactory>;
|
|
886
|
+
}): Graph;
|
|
887
|
+
/**
|
|
888
|
+
* ECMAScript `JSON.stringify` hook — returns the same object as
|
|
889
|
+
* {@link Graph.snapshot}. Makes `JSON.stringify(graph)` "just work"
|
|
890
|
+
* without double-encoding.
|
|
891
|
+
*/
|
|
892
|
+
toJSON(): GraphPersistSnapshot;
|
|
893
|
+
/**
|
|
894
|
+
* Unified persistence surface (§3.8). Cascades snapshot records through
|
|
895
|
+
* one or more {@link StorageTier}s, each with its own `debounceMs` /
|
|
896
|
+
* `compactEvery` cadence and independent diff baseline.
|
|
897
|
+
*
|
|
898
|
+
* Subscription gates on {@link messageTier} ≥ 3 (DATA/RESOLVED/terminal),
|
|
899
|
+
* never on tier-0/1/2 control waves (START/DIRTY/INVALIDATE/PAUSE/RESUME)
|
|
900
|
+
* or tier-5 TEARDOWN (graceful shutdown is the caller's responsibility).
|
|
901
|
+
*
|
|
902
|
+
* Per-tier cadence lets the hot tier stay sync while cold tiers absorb
|
|
903
|
+
* async writes without blocking the hot path. Each tier holds its own
|
|
904
|
+
* `{lastSnapshot, lastVersionFingerprint}` so cold-tier diff baselines
|
|
905
|
+
* aren't polluted by hot-tier flushes. Tiers with `debounceMs === 0`
|
|
906
|
+
* share a single snapshot computation per observe event; debounced tiers
|
|
907
|
+
* compute their own snapshot when their timer fires.
|
|
908
|
+
*/
|
|
909
|
+
attachStorage(tiers: readonly StorageTier[], options?: GraphAttachStorageOptions): StorageHandle;
|
|
910
|
+
/**
|
|
911
|
+
* Try tiers in order (hottest first); apply the first record that hits
|
|
912
|
+
* via {@link Graph.restore}. Returns `true` if any tier produced a
|
|
913
|
+
* restorable snapshot, `false` if all missed.
|
|
914
|
+
*
|
|
915
|
+
* Resilience: a tier that returns data which cannot be restored (load
|
|
916
|
+
* throws, shape unrecognized, or `restore()` itself throws) does not abort
|
|
917
|
+
* the cascade — the error is routed through `onError` (if supplied) and
|
|
918
|
+
* the next colder tier is tried. This mirrors how a multi-tier cache
|
|
919
|
+
* falls through on a corrupt hot entry.
|
|
920
|
+
*
|
|
921
|
+
* Note: `restore()` mutates state incrementally. If a restore throws
|
|
922
|
+
* partway through, the graph may hold a mixed state (some slices from
|
|
923
|
+
* the bad tier, some pre-existing). A subsequent successful tier's
|
|
924
|
+
* `restore()` overwrites the overlapping slices.
|
|
925
|
+
*
|
|
926
|
+
* Internal helper shared by {@link Graph.attachStorage}'s `autoRestore`
|
|
927
|
+
* option and the static {@link Graph.fromStorage} factory.
|
|
928
|
+
*/
|
|
929
|
+
private _cascadeRestore;
|
|
930
|
+
/**
|
|
931
|
+
* Construct a fresh {@link Graph} pre-hydrated from the first tier that
|
|
932
|
+
* hits. Delegates topology reconstruction to {@link Graph.fromSnapshot}
|
|
933
|
+
* on `"full"` records and direct {@link Graph.restore} on bare snapshots.
|
|
934
|
+
*
|
|
935
|
+
* Always asynchronous — awaits `tier.load()` for async tier support even
|
|
936
|
+
* when all tiers are sync. Callers that know they only pass sync tiers
|
|
937
|
+
* can safely `await` immediately.
|
|
938
|
+
*
|
|
939
|
+
* @throws If no tier holds a restorable record matching `name` *and* no
|
|
940
|
+
* `factories` override is provided for dynamic nodes.
|
|
941
|
+
*/
|
|
942
|
+
static fromStorage(name: string, tiers: readonly StorageTier[], opts?: GraphOptions & {
|
|
943
|
+
factories?: Record<string, GraphNodeFactory>;
|
|
944
|
+
/**
|
|
945
|
+
* Called when a tier throws during `load()` or when
|
|
946
|
+
* {@link Graph.fromSnapshot} rejects a tier's record. The cascade
|
|
947
|
+
* falls through to the next colder tier regardless.
|
|
948
|
+
*/
|
|
949
|
+
onError?: (err: unknown, tier: StorageTier) => void;
|
|
950
|
+
}): Promise<Graph>;
|
|
951
|
+
private _annotations;
|
|
952
|
+
private readonly _traceRing;
|
|
953
|
+
/**
|
|
954
|
+
* Unified reasoning trace: write annotations or read the ring buffer.
|
|
955
|
+
*
|
|
956
|
+
* Write: `graph.trace("path", "reason")` — attaches a reasoning annotation
|
|
957
|
+
* to a node, capturing *why* an AI agent set a value. Unknown paths are
|
|
958
|
+
* silently dropped (matching `observe` resilience). No-op when
|
|
959
|
+
* `config.inspectorEnabled` is `false`.
|
|
960
|
+
*
|
|
961
|
+
* Read: `graph.trace()` — returns a chronological log of all annotations.
|
|
962
|
+
* Returns `[]` when `config.inspectorEnabled` is `false`.
|
|
963
|
+
*/
|
|
964
|
+
trace(path: string, reason: string, opts?: {
|
|
965
|
+
actor?: Actor;
|
|
966
|
+
}): void;
|
|
967
|
+
trace(): readonly TraceEntry[];
|
|
968
|
+
/**
|
|
969
|
+
* Latest reason annotation attached to `path` via {@link Graph.trace},
|
|
970
|
+
* or `undefined` if none. `describe()` surfaces this via the `reason`
|
|
971
|
+
* field on each node entry (when present).
|
|
972
|
+
*/
|
|
973
|
+
annotation(path: string): string | undefined;
|
|
974
|
+
/**
|
|
975
|
+
* Clear all reasoning-trace state (both the per-path annotations map and
|
|
976
|
+
* the ring buffer). Useful for long-running processes that want periodic
|
|
977
|
+
* resets, or tests that need a clean slate.
|
|
978
|
+
*/
|
|
979
|
+
clearTrace(): void;
|
|
980
|
+
/**
|
|
981
|
+
* Remove trace entries matching `predicate`. Returns the number of
|
|
982
|
+
* entries removed. Does not touch the per-path annotations map — call
|
|
983
|
+
* {@link Graph.clearTrace} for a full reset.
|
|
984
|
+
*/
|
|
985
|
+
pruneTrace(predicate: (entry: TraceEntry) => boolean): number;
|
|
986
|
+
/**
|
|
987
|
+
* Computes structural + value diff between two {@link Graph.describe} snapshots.
|
|
988
|
+
*
|
|
989
|
+
* @param a - Earlier describe output.
|
|
990
|
+
* @param b - Later describe output.
|
|
991
|
+
* @returns Added/removed nodes, changed fields, and edge deltas.
|
|
992
|
+
*/
|
|
993
|
+
static diff(a: GraphDescribeOutput, b: GraphDescribeOutput): GraphDiffResult;
|
|
994
|
+
}
|
|
995
|
+
/** Entry in the reasoning trace ring buffer (roadmap 3.3). */
|
|
996
|
+
type TraceEntry = {
|
|
997
|
+
path: string;
|
|
998
|
+
reason: string;
|
|
999
|
+
timestamp_ns: number;
|
|
1000
|
+
/**
|
|
1001
|
+
* Actor that produced the annotation (optional). Enables multi-agent
|
|
1002
|
+
* attribution: distinguish "LLM set this rootCause" from "human approved
|
|
1003
|
+
* this intervention" in the trace log.
|
|
1004
|
+
*/
|
|
1005
|
+
actor?: Actor;
|
|
1006
|
+
};
|
|
1007
|
+
/** Result of {@link Graph.diff}. */
|
|
1008
|
+
type GraphDiffResult = {
|
|
1009
|
+
nodesAdded: string[];
|
|
1010
|
+
nodesRemoved: string[];
|
|
1011
|
+
nodesChanged: GraphDiffChange[];
|
|
1012
|
+
/**
|
|
1013
|
+
* V0 version bumps (same `v.id`, different `v.version`). Surfaced even
|
|
1014
|
+
* when values are identical — the bump itself is audit-meaningful.
|
|
1015
|
+
*/
|
|
1016
|
+
versionChanges: GraphVersionChange[];
|
|
1017
|
+
edgesAdded: Array<{
|
|
1018
|
+
from: string;
|
|
1019
|
+
to: string;
|
|
1020
|
+
}>;
|
|
1021
|
+
edgesRemoved: Array<{
|
|
1022
|
+
from: string;
|
|
1023
|
+
to: string;
|
|
1024
|
+
}>;
|
|
1025
|
+
subgraphsAdded: string[];
|
|
1026
|
+
subgraphsRemoved: string[];
|
|
1027
|
+
};
|
|
1028
|
+
/**
|
|
1029
|
+
* WAL-oriented diff — extends {@link GraphDiffResult} with the full node
|
|
1030
|
+
* slice for each added path so {@link replayWAL} can reconstruct nodes added
|
|
1031
|
+
* between full anchors (topology mutations inside a `compactEvery` window).
|
|
1032
|
+
*
|
|
1033
|
+
* `Graph.diff()` returns the audit shape (no payload); `attachStorage` writes
|
|
1034
|
+
* this WAL shape. The two shapes stay structurally compatible — `GraphWALDiff`
|
|
1035
|
+
* is a superset.
|
|
1036
|
+
*/
|
|
1037
|
+
type GraphWALDiff = GraphDiffResult & {
|
|
1038
|
+
/**
|
|
1039
|
+
* Full node slices for every path in `nodesAdded`, keyed by path. Applied
|
|
1040
|
+
* verbatim to `snapshot.nodes[path]` during replay.
|
|
1041
|
+
*/
|
|
1042
|
+
nodesAddedFull: Record<string, DescribeNodeOutput>;
|
|
1043
|
+
};
|
|
1044
|
+
/**
|
|
1045
|
+
* Build a WAL-ready diff between two snapshots: the structural diff from
|
|
1046
|
+
* {@link Graph.diff} plus the full node slice for each added path (pulled
|
|
1047
|
+
* from `b.nodes`). Callers that only need the audit shape should use
|
|
1048
|
+
* `Graph.diff` directly.
|
|
1049
|
+
*/
|
|
1050
|
+
declare function diffForWAL(a: GraphDescribeOutput, b: GraphDescribeOutput): GraphWALDiff;
|
|
1051
|
+
/** A single field change within a diff. */
|
|
1052
|
+
type GraphDiffChange = {
|
|
1053
|
+
path: string;
|
|
1054
|
+
field: string;
|
|
1055
|
+
from: unknown;
|
|
1056
|
+
to: unknown;
|
|
1057
|
+
};
|
|
1058
|
+
/** A single V0 version bump within a diff. */
|
|
1059
|
+
type GraphVersionChange = {
|
|
1060
|
+
path: string;
|
|
1061
|
+
id: string;
|
|
1062
|
+
from: number;
|
|
1063
|
+
to: number;
|
|
1064
|
+
};
|
|
1065
|
+
/** Audit record returned by {@link Graph.remove}. */
|
|
1066
|
+
type GraphRemoveAudit = {
|
|
1067
|
+
/** Whether the removed entry was a local node or a mount. */
|
|
1068
|
+
kind: "node" | "mount";
|
|
1069
|
+
/**
|
|
1070
|
+
* Primary nodes torn down by this `remove()`. For `kind: "node"` contains
|
|
1071
|
+
* just the removed name; for `kind: "mount"` lists every primary node in
|
|
1072
|
+
* the unmounted subtree (qualified paths relative to the mount point,
|
|
1073
|
+
* sorted).
|
|
1074
|
+
*/
|
|
1075
|
+
nodes: string[];
|
|
1076
|
+
/**
|
|
1077
|
+
* Mounted subgraphs that were unmounted. For `kind: "node"` this is empty;
|
|
1078
|
+
* for `kind: "mount"` starts with the top-level mount name and lists its
|
|
1079
|
+
* descendants in depth-first order.
|
|
1080
|
+
*/
|
|
1081
|
+
mounts: string[];
|
|
1082
|
+
};
|
|
1083
|
+
/** Direction for {@link reachable} graph traversal. */
|
|
1084
|
+
type ReachableDirection = "upstream" | "downstream";
|
|
1085
|
+
/** Options for {@link reachable}. */
|
|
1086
|
+
type ReachableOptions = {
|
|
1087
|
+
/** Maximum hop depth from `from` (0 returns `[]`). Omit for unbounded traversal. */
|
|
1088
|
+
maxDepth?: number;
|
|
1089
|
+
/**
|
|
1090
|
+
* Traverse both directions in one pass (union of upstream + downstream).
|
|
1091
|
+
* Ignores the `direction` arg when set.
|
|
1092
|
+
*/
|
|
1093
|
+
both?: boolean;
|
|
1094
|
+
/**
|
|
1095
|
+
* Return the richer {@link ReachableResult} shape (paths + per-path
|
|
1096
|
+
* hop depth + truncation flag) instead of the flat sorted string array.
|
|
1097
|
+
*/
|
|
1098
|
+
withDetail?: boolean;
|
|
1099
|
+
};
|
|
1100
|
+
/** Rich reachable result (opt-in via `{withDetail: true}`). */
|
|
1101
|
+
type ReachableResult = {
|
|
1102
|
+
/** Reachable paths, sorted lexicographically. */
|
|
1103
|
+
paths: string[];
|
|
1104
|
+
/** Hop depth from `from` to each reachable path. */
|
|
1105
|
+
depths: Map<string, number>;
|
|
1106
|
+
/** True when traversal hit `maxDepth` and some neighbors were not explored. */
|
|
1107
|
+
truncated: boolean;
|
|
1108
|
+
};
|
|
1109
|
+
/**
|
|
1110
|
+
* Reachability query over a {@link Graph.describe} snapshot.
|
|
1111
|
+
*
|
|
1112
|
+
* Traversal follows `deps` (upstream) and reverse-`deps` (downstream). Edges
|
|
1113
|
+
* are derived from deps post Unit 7, so `edges[]` in the snapshot is
|
|
1114
|
+
* redundant with deps — it's walked defensively in case a caller supplied a
|
|
1115
|
+
* pre-Unit-7 snapshot.
|
|
1116
|
+
*
|
|
1117
|
+
* @param described - `graph.describe()` output to traverse.
|
|
1118
|
+
* @param from - Start path (qualified node path).
|
|
1119
|
+
* @param direction - Traversal direction (ignored when `opts.both` is `true`).
|
|
1120
|
+
* @param options - Optional `maxDepth`, `both`, `withDetail`.
|
|
1121
|
+
* @returns Sorted paths (flat) — or {@link ReachableResult} when `withDetail: true`.
|
|
1122
|
+
*/
|
|
1123
|
+
declare function reachable(described: GraphDescribeOutput, from: string, direction: ReachableDirection, options?: ReachableOptions & {
|
|
1124
|
+
withDetail: true;
|
|
1125
|
+
}): ReachableResult;
|
|
1126
|
+
declare function reachable(described: GraphDescribeOutput, from: string, direction: ReachableDirection, options?: ReachableOptions): string[];
|
|
1127
|
+
|
|
1128
|
+
export { diffForWAL as A, graphProfile as B, reachable as C, type DescribeFilter as D, Graph as G, type NodeProfile as N, type ObserveDetail as O, type ReachableDirection as R, type TraceEntry as T, type GraphOptions as a, type GraphAttachStorageOptions as b, type GraphProfileResult as c, type GraphProfileOptions as d, GRAPH_META_SEGMENT as e, type GraphActorOptions as f, type GraphCheckpointRecord as g, type GraphDescribeOptions as h, type GraphDescribeOutput as i, type GraphDiagramDirection as j, type GraphDiagramOptions as k, type GraphDiffChange as l, type GraphDiffResult as m, type GraphFactoryContext as n, type GraphNodeFactory as o, type GraphObserveAll as p, type GraphObserveOne as q, type GraphPersistSnapshot as r, type GraphVersionChange as s, type GraphWALDiff as t, type ObserveEvent as u, type ObserveOptions as v, type ObserveResult as w, type ObserveTheme as x, type ObserveThemeName as y, type ReachableOptions as z };
|