@graphrefly/graphrefly 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +8 -0
  2. package/dist/{chunk-QOWVNWOC.js → chunk-3ZWCKRHX.js} +27 -25
  3. package/dist/{chunk-QOWVNWOC.js.map → chunk-3ZWCKRHX.js.map} +1 -1
  4. package/dist/chunk-6LDQFTYS.js +102 -0
  5. package/dist/chunk-6LDQFTYS.js.map +1 -0
  6. package/dist/{chunk-IAHGTNOZ.js → chunk-AMCG74RZ.js} +193 -24
  7. package/dist/chunk-AMCG74RZ.js.map +1 -0
  8. package/dist/{chunk-L2GLW2U7.js → chunk-BVZYTZ5H.js} +9 -103
  9. package/dist/chunk-BVZYTZ5H.js.map +1 -0
  10. package/dist/chunk-FQMKGR6L.js +330 -0
  11. package/dist/chunk-FQMKGR6L.js.map +1 -0
  12. package/dist/chunk-HXZEYDUR.js +94 -0
  13. package/dist/chunk-HXZEYDUR.js.map +1 -0
  14. package/dist/{chunk-EVR6UFUV.js → chunk-IZYUSJC7.js} +16 -14
  15. package/dist/{chunk-EVR6UFUV.js.map → chunk-IZYUSJC7.js.map} +1 -1
  16. package/dist/chunk-J22W6HV3.js +107 -0
  17. package/dist/chunk-J22W6HV3.js.map +1 -0
  18. package/dist/{chunk-HWPIFSW2.js → chunk-JSCT3CR4.js} +6 -4
  19. package/dist/{chunk-HWPIFSW2.js.map → chunk-JSCT3CR4.js.map} +1 -1
  20. package/dist/chunk-JYXEWPH4.js +62 -0
  21. package/dist/chunk-JYXEWPH4.js.map +1 -0
  22. package/dist/{chunk-TKE3JGOH.js → chunk-LCE3GF5P.js} +5 -692
  23. package/dist/chunk-LCE3GF5P.js.map +1 -0
  24. package/dist/chunk-MJ2NKQQL.js +119 -0
  25. package/dist/chunk-MJ2NKQQL.js.map +1 -0
  26. package/dist/chunk-N6UR7YVY.js +198 -0
  27. package/dist/chunk-N6UR7YVY.js.map +1 -0
  28. package/dist/chunk-OHISZPOJ.js +97 -0
  29. package/dist/chunk-OHISZPOJ.js.map +1 -0
  30. package/dist/{chunk-5DJTTKX3.js → chunk-PHOUUNK7.js} +74 -111
  31. package/dist/chunk-PHOUUNK7.js.map +1 -0
  32. package/dist/{chunk-PY4XCDLR.js → chunk-RB6QPHJ7.js} +8 -6
  33. package/dist/{chunk-PY4XCDLR.js.map → chunk-RB6QPHJ7.js.map} +1 -1
  34. package/dist/chunk-SN4YWWYO.js +171 -0
  35. package/dist/chunk-SN4YWWYO.js.map +1 -0
  36. package/dist/chunk-SX52TAR4.js +110 -0
  37. package/dist/chunk-SX52TAR4.js.map +1 -0
  38. package/dist/{chunk-XOFWRC73.js → chunk-THTWHNU4.js} +319 -24
  39. package/dist/chunk-THTWHNU4.js.map +1 -0
  40. package/dist/{chunk-H4RVA4VE.js → chunk-VYPWMZ6H.js} +2 -2
  41. package/dist/chunk-XGPU467M.js +136 -0
  42. package/dist/chunk-XGPU467M.js.map +1 -0
  43. package/dist/chunk-ZQMEI34O.js +713 -0
  44. package/dist/chunk-ZQMEI34O.js.map +1 -0
  45. package/dist/compat/index.cjs +7656 -0
  46. package/dist/compat/index.cjs.map +1 -0
  47. package/dist/compat/index.d.cts +18 -0
  48. package/dist/compat/index.d.ts +18 -0
  49. package/dist/compat/index.js +49 -0
  50. package/dist/compat/index.js.map +1 -0
  51. package/dist/compat/jotai/index.cjs +2048 -0
  52. package/dist/compat/jotai/index.cjs.map +1 -0
  53. package/dist/compat/jotai/index.d.cts +2 -0
  54. package/dist/compat/jotai/index.d.ts +2 -0
  55. package/dist/compat/jotai/index.js +9 -0
  56. package/dist/compat/jotai/index.js.map +1 -0
  57. package/dist/compat/nanostores/index.cjs +2175 -0
  58. package/dist/compat/nanostores/index.cjs.map +1 -0
  59. package/dist/compat/nanostores/index.d.cts +2 -0
  60. package/dist/compat/nanostores/index.d.ts +2 -0
  61. package/dist/compat/nanostores/index.js +23 -0
  62. package/dist/compat/nanostores/index.js.map +1 -0
  63. package/dist/compat/nestjs/index.cjs +350 -16
  64. package/dist/compat/nestjs/index.cjs.map +1 -1
  65. package/dist/compat/nestjs/index.d.cts +6 -6
  66. package/dist/compat/nestjs/index.d.ts +6 -6
  67. package/dist/compat/nestjs/index.js +10 -9
  68. package/dist/compat/react/index.cjs +141 -0
  69. package/dist/compat/react/index.cjs.map +1 -0
  70. package/dist/compat/react/index.d.cts +2 -0
  71. package/dist/compat/react/index.d.ts +2 -0
  72. package/dist/compat/react/index.js +12 -0
  73. package/dist/compat/react/index.js.map +1 -0
  74. package/dist/compat/solid/index.cjs +128 -0
  75. package/dist/compat/solid/index.cjs.map +1 -0
  76. package/dist/compat/solid/index.d.cts +2 -0
  77. package/dist/compat/solid/index.d.ts +2 -0
  78. package/dist/compat/solid/index.js +12 -0
  79. package/dist/compat/solid/index.js.map +1 -0
  80. package/dist/compat/svelte/index.cjs +131 -0
  81. package/dist/compat/svelte/index.cjs.map +1 -0
  82. package/dist/compat/svelte/index.d.cts +2 -0
  83. package/dist/compat/svelte/index.d.ts +2 -0
  84. package/dist/compat/svelte/index.js +12 -0
  85. package/dist/compat/svelte/index.js.map +1 -0
  86. package/dist/compat/vue/index.cjs +146 -0
  87. package/dist/compat/vue/index.cjs.map +1 -0
  88. package/dist/compat/vue/index.d.cts +3 -0
  89. package/dist/compat/vue/index.d.ts +3 -0
  90. package/dist/compat/vue/index.js +12 -0
  91. package/dist/compat/vue/index.js.map +1 -0
  92. package/dist/compat/zustand/index.cjs +4931 -0
  93. package/dist/compat/zustand/index.cjs.map +1 -0
  94. package/dist/compat/zustand/index.d.cts +5 -0
  95. package/dist/compat/zustand/index.d.ts +5 -0
  96. package/dist/compat/zustand/index.js +12 -0
  97. package/dist/compat/zustand/index.js.map +1 -0
  98. package/dist/core/index.cjs +53 -4
  99. package/dist/core/index.cjs.map +1 -1
  100. package/dist/core/index.d.cts +3 -3
  101. package/dist/core/index.d.ts +3 -3
  102. package/dist/core/index.js +26 -24
  103. package/dist/demo-shell-26p5fVxn.d.cts +102 -0
  104. package/dist/demo-shell-DEp-nMTl.d.ts +102 -0
  105. package/dist/extra/index.cjs +222 -110
  106. package/dist/extra/index.cjs.map +1 -1
  107. package/dist/extra/index.d.cts +5 -4
  108. package/dist/extra/index.d.ts +5 -4
  109. package/dist/extra/index.js +6 -5
  110. package/dist/extra/sources.cjs +2486 -0
  111. package/dist/extra/sources.cjs.map +1 -0
  112. package/dist/extra/sources.d.cts +465 -0
  113. package/dist/extra/sources.d.ts +465 -0
  114. package/dist/extra/sources.js +57 -0
  115. package/dist/extra/sources.js.map +1 -0
  116. package/dist/graph/index.cjs +408 -14
  117. package/dist/graph/index.cjs.map +1 -1
  118. package/dist/graph/index.d.cts +5 -5
  119. package/dist/graph/index.d.ts +5 -5
  120. package/dist/graph/index.js +13 -5
  121. package/dist/{graph-B6NFqv3z.d.ts → graph-6tZ5jEzr.d.cts} +195 -4
  122. package/dist/{graph-D-3JIQme.d.cts → graph-DQ69XU0g.d.ts} +195 -4
  123. package/dist/index-B4MP_8V_.d.cts +37 -0
  124. package/dist/index-BEfE8H_G.d.cts +121 -0
  125. package/dist/{index-OXImXMq6.d.ts → index-BW1z3BN9.d.ts} +18 -196
  126. package/dist/index-BYOHF0zP.d.ts +34 -0
  127. package/dist/index-B_IP40nB.d.cts +36 -0
  128. package/dist/index-Bd_fwmLf.d.cts +45 -0
  129. package/dist/{index-Ds23Wvou.d.ts → index-BeIdBfcb.d.cts} +120 -573
  130. package/dist/index-BjI6ty9z.d.ts +121 -0
  131. package/dist/index-Bxb5ZYc9.d.cts +34 -0
  132. package/dist/{index-BJB7t9gg.d.cts → index-C0ZXMaXO.d.cts} +2 -2
  133. package/dist/{index-DKE1EATr.d.cts → index-C8mdwMXc.d.cts} +18 -196
  134. package/dist/index-CDAjUFIv.d.ts +36 -0
  135. package/dist/index-CPgZ5wRl.d.ts +44 -0
  136. package/dist/{index-AMWewNDe.d.cts → index-CUwyr1Kk.d.cts} +33 -4
  137. package/dist/index-CUyrtuOf.d.cts +127 -0
  138. package/dist/{index-C-TXEa7C.d.ts → index-CY2TljO4.d.ts} +2 -2
  139. package/dist/index-CmnuOibw.d.ts +37 -0
  140. package/dist/{index-DiobMNwE.d.ts → index-CuYwdKO-.d.ts} +3 -3
  141. package/dist/index-DFhjO4Gg.d.cts +44 -0
  142. package/dist/{index-Ch0IpIO0.d.cts → index-DdD5MVDL.d.ts} +120 -573
  143. package/dist/index-DrISNAOm.d.ts +45 -0
  144. package/dist/index-QBpffFW-.d.cts +86 -0
  145. package/dist/{index-J7Kc0oIQ.d.cts → index-_oMEWlDq.d.cts} +3 -3
  146. package/dist/{index-CYkjxu3s.d.ts → index-eJ6T_qGM.d.ts} +33 -4
  147. package/dist/index-qldRdbQw.d.ts +86 -0
  148. package/dist/index-xdGjv0nO.d.ts +127 -0
  149. package/dist/index.cjs +1780 -176
  150. package/dist/index.cjs.map +1 -1
  151. package/dist/index.d.cts +1007 -648
  152. package/dist/index.d.ts +1007 -648
  153. package/dist/index.js +1202 -1172
  154. package/dist/index.js.map +1 -1
  155. package/dist/{meta-CnkLA_43.d.ts → meta-BGqSZ7mt.d.ts} +1 -1
  156. package/dist/{meta-DWbkoq1s.d.cts → meta-C0-8XW6Q.d.cts} +1 -1
  157. package/dist/{node-B-f-Lu-k.d.cts → node-C_IBuvX2.d.cts} +26 -1
  158. package/dist/{node-B-f-Lu-k.d.ts → node-C_IBuvX2.d.ts} +26 -1
  159. package/dist/{observable-DBnrwcar.d.cts → observable-Crr1jgzx.d.cts} +1 -1
  160. package/dist/{observable-uP-wy_uK.d.ts → observable-DCk45RH5.d.ts} +1 -1
  161. package/dist/patterns/demo-shell.cjs +5604 -0
  162. package/dist/patterns/demo-shell.cjs.map +1 -0
  163. package/dist/patterns/demo-shell.d.cts +6 -0
  164. package/dist/patterns/demo-shell.d.ts +6 -0
  165. package/dist/patterns/demo-shell.js +15 -0
  166. package/dist/patterns/demo-shell.js.map +1 -0
  167. package/dist/patterns/reactive-layout/index.cjs +355 -13
  168. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  169. package/dist/patterns/reactive-layout/index.d.cts +6 -5
  170. package/dist/patterns/reactive-layout/index.d.ts +6 -5
  171. package/dist/patterns/reactive-layout/index.js +15 -12
  172. package/dist/reactive-layout-BaOQefHu.d.cts +183 -0
  173. package/dist/reactive-layout-D9gejYXE.d.ts +183 -0
  174. package/dist/{storage-BuTdpCI1.d.cts → storage-BMycWEh2.d.ts} +9 -1
  175. package/dist/{storage-F2X1U1x0.d.ts → storage-DiqWHzVI.d.cts} +9 -1
  176. package/package.json +32 -2
  177. package/dist/chunk-5DJTTKX3.js.map +0 -1
  178. package/dist/chunk-IAHGTNOZ.js.map +0 -1
  179. package/dist/chunk-L2GLW2U7.js.map +0 -1
  180. package/dist/chunk-MW4VAKAO.js +0 -47
  181. package/dist/chunk-MW4VAKAO.js.map +0 -1
  182. package/dist/chunk-TKE3JGOH.js.map +0 -1
  183. package/dist/chunk-XOFWRC73.js.map +0 -1
  184. /package/dist/{chunk-H4RVA4VE.js.map → chunk-VYPWMZ6H.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,3 +1,32 @@
1
+ import {
2
+ reactive_layout_exports
3
+ } from "./chunk-ZQMEI34O.js";
4
+ import {
5
+ compat_exports,
6
+ signals_exports
7
+ } from "./chunk-SN4YWWYO.js";
8
+ import {
9
+ nanostores_exports
10
+ } from "./chunk-N6UR7YVY.js";
11
+ import {
12
+ cqrs_exports,
13
+ nestjs_exports
14
+ } from "./chunk-IZYUSJC7.js";
15
+ import {
16
+ react_exports
17
+ } from "./chunk-J22W6HV3.js";
18
+ import {
19
+ solid_exports
20
+ } from "./chunk-HXZEYDUR.js";
21
+ import {
22
+ svelte_exports
23
+ } from "./chunk-OHISZPOJ.js";
24
+ import {
25
+ vue_exports
26
+ } from "./chunk-MJ2NKQQL.js";
27
+ import {
28
+ zustand_exports
29
+ } from "./chunk-JYXEWPH4.js";
1
30
  import {
2
31
  CircuitOpenError,
3
32
  NS_PER_MS,
@@ -48,6 +77,7 @@ import {
48
77
  fromCSV,
49
78
  fromClickHouseWatch,
50
79
  fromDrizzle,
80
+ fromFSWatch,
51
81
  fromGitHook,
52
82
  fromHTTP,
53
83
  fromHTTPPoll,
@@ -148,33 +178,29 @@ import {
148
178
  workerBridge,
149
179
  workerSelf,
150
180
  zip
151
- } from "./chunk-IAHGTNOZ.js";
152
- import {
153
- cqrs_exports,
154
- nestjs_exports
155
- } from "./chunk-EVR6UFUV.js";
156
- import {
157
- core_exports
158
- } from "./chunk-QOWVNWOC.js";
181
+ } from "./chunk-AMCG74RZ.js";
159
182
  import {
160
183
  NativeLogBackend,
161
184
  createWatermarkController,
162
185
  reactiveLog,
163
186
  toObservable
164
- } from "./chunk-PY4XCDLR.js";
187
+ } from "./chunk-RB6QPHJ7.js";
188
+ import {
189
+ core_exports
190
+ } from "./chunk-3ZWCKRHX.js";
165
191
  import {
166
- graph_exports
167
- } from "./chunk-MW4VAKAO.js";
192
+ graph_exports,
193
+ watchTopologyTree
194
+ } from "./chunk-6LDQFTYS.js";
168
195
  import {
169
- analyzeAndMeasure,
170
- computeLineBreaks,
171
- reactive_layout_exports
172
- } from "./chunk-TKE3JGOH.js";
196
+ demo_shell_exports
197
+ } from "./chunk-FQMKGR6L.js";
198
+ import "./chunk-LCE3GF5P.js";
173
199
  import {
174
200
  domainMeta,
175
201
  trackingKey,
176
202
  tryIncrementBounded
177
- } from "./chunk-HWPIFSW2.js";
203
+ } from "./chunk-JSCT3CR4.js";
178
204
  import {
179
205
  cached,
180
206
  empty,
@@ -186,7 +212,6 @@ import {
186
212
  fromAsyncIter,
187
213
  fromCron,
188
214
  fromEvent,
189
- fromFSWatch,
190
215
  fromIter,
191
216
  fromPromise,
192
217
  fromRaf,
@@ -204,53 +229,35 @@ import {
204
229
  shareReplay,
205
230
  throwError,
206
231
  toArray
207
- } from "./chunk-L2GLW2U7.js";
232
+ } from "./chunk-BVZYTZ5H.js";
208
233
  import {
209
234
  GRAPH_META_SEGMENT,
210
235
  Graph,
211
236
  OVERHEAD,
212
237
  SIZEOF_SYMBOL,
238
+ SNAPSHOT_VERSION,
213
239
  diffForWAL,
240
+ explainPath,
214
241
  graphProfile,
215
242
  reachable,
216
243
  sizeof
217
- } from "./chunk-XOFWRC73.js";
218
- import {
219
- describeNode,
220
- resolveDescribeFields
221
- } from "./chunk-H4RVA4VE.js";
244
+ } from "./chunk-THTWHNU4.js";
222
245
  import {
223
246
  ResettableTimer
224
247
  } from "./chunk-7TAQJHQV.js";
225
248
  import {
226
- COMPLETE,
227
- COMPLETE_MSG,
228
- COMPLETE_ONLY_BATCH,
229
- DATA,
249
+ resolveDescribeFields
250
+ } from "./chunk-VYPWMZ6H.js";
251
+ import {
252
+ jotai_exports
253
+ } from "./chunk-XGPU467M.js";
254
+ import {
230
255
  DEFAULT_ACTOR,
231
- DIRTY,
232
- DIRTY_MSG,
233
- DIRTY_ONLY_BATCH,
234
256
  ENVELOPE_VERSION,
235
- ERROR,
236
257
  GraphReFlyConfig,
237
258
  GuardDenied,
238
- INVALIDATE,
239
- INVALIDATE_MSG,
240
- INVALIDATE_ONLY_BATCH,
241
259
  JsonCodec,
242
260
  NodeImpl,
243
- PAUSE,
244
- RESOLVED,
245
- RESOLVED_MSG,
246
- RESOLVED_ONLY_BATCH,
247
- RESUME,
248
- START,
249
- START_MSG,
250
- TEARDOWN,
251
- TEARDOWN_MSG,
252
- TEARDOWN_ONLY_BATCH,
253
- __export,
254
261
  accessHintForGuard,
255
262
  advanceVersion,
256
263
  autoTrackNode,
@@ -281,855 +288,61 @@ import {
281
288
  replayWAL,
282
289
  state,
283
290
  wallClockNs
284
- } from "./chunk-5DJTTKX3.js";
285
-
286
- // src/compat/index.ts
287
- var compat_exports = {};
288
- __export(compat_exports, {
289
- jotai: () => jotai_exports,
290
- nanostores: () => nanostores_exports,
291
- nestjs: () => nestjs_exports,
292
- react: () => react_exports,
293
- signals: () => signals_exports,
294
- solid: () => solid_exports,
295
- svelte: () => svelte_exports,
296
- vue: () => vue_exports,
297
- zustand: () => zustand_exports
298
- });
299
-
300
- // src/compat/jotai/index.ts
301
- var jotai_exports = {};
302
- __export(jotai_exports, {
303
- atom: () => atom
304
- });
305
- function atom(initialOrRead, writeOrOptions, options) {
306
- if (typeof initialOrRead === "function") {
307
- const read = initialOrRead;
308
- if (typeof writeOrOptions === "function") {
309
- return createDerivedAtom(read, writeOrOptions, options);
310
- }
311
- return createDerivedAtom(read, void 0, writeOrOptions);
312
- }
313
- return createPrimitiveAtom(initialOrRead, writeOrOptions);
314
- }
315
- function pull(n) {
316
- let val = n.cache;
317
- let err;
318
- const unsub = n.subscribe((msgs) => {
319
- for (const [t, v] of msgs) {
320
- if (t === DATA) val = v;
321
- if (t === ERROR) err = v;
322
- }
323
- });
324
- unsub();
325
- if (err) throw err;
326
- return val;
327
- }
328
- function createPrimitiveAtom(initial, options) {
329
- const n = state(initial, {
330
- ...options,
331
- resubscribable: true,
332
- resetOnTeardown: true
333
- });
334
- return {
335
- get: () => {
336
- if (n.status === "sentinel") {
337
- return pull(n);
338
- }
339
- return n.cache;
340
- },
341
- // Use `n.emit` (not raw `n.down`) so writes go through the framed
342
- // emit pipeline: bundle() auto-prefixes DIRTY (diamond-safe wave
343
- // coordination) and the equals check folds same-value writes to
344
- // RESOLVED (no spurious subscriber fires).
345
- set: (value) => n.emit(value),
346
- update: (fn) => {
347
- const current = n.status === "sentinel" ? pull(n) : n.cache;
348
- n.emit(fn(current));
349
- },
350
- subscribe: (cb) => {
351
- let initial2 = true;
352
- return n.subscribe((msgs) => {
353
- for (const [t, v] of msgs) {
354
- if (t === DATA) {
355
- if (initial2) {
356
- initial2 = false;
357
- continue;
358
- }
359
- cb(v);
360
- }
361
- }
362
- });
363
- },
364
- meta: n.meta,
365
- _node: n
366
- };
367
- }
368
- function createDerivedAtom(read, write, options) {
369
- const n = autoTrackNode(
370
- (track) => read((a) => {
371
- const dn = a._node;
372
- if (dn.status === "sentinel") {
373
- pull(dn);
374
- }
375
- return track(dn);
376
- }),
377
- {
378
- ...options,
379
- resubscribable: true,
380
- resetOnTeardown: true
381
- }
382
- );
383
- const result = {
384
- get: () => {
385
- if (n.status === "sentinel") {
386
- return pull(n);
387
- }
388
- return n.cache;
389
- },
390
- subscribe: (cb) => {
391
- let initial = true;
392
- return n.subscribe((msgs) => {
393
- for (const [t, v] of msgs) {
394
- if (t === DATA) {
395
- if (initial) {
396
- initial = false;
397
- continue;
398
- }
399
- cb(v);
400
- }
401
- }
402
- });
403
- },
404
- meta: n.meta,
405
- _node: n
406
- };
407
- if (write) {
408
- const getFn = (a) => a.get();
409
- const setFn = (a, value) => a.set(value);
410
- const writable = result;
411
- writable.set = (value) => write(getFn, setFn, value);
412
- writable.update = (fn) => {
413
- const current = n.status === "sentinel" ? pull(n) : n.cache;
414
- return write(getFn, setFn, fn(current));
415
- };
416
- return writable;
417
- }
418
- return result;
419
- }
420
-
421
- // src/compat/nanostores/index.ts
422
- var nanostores_exports = {};
423
- __export(nanostores_exports, {
424
- action: () => action,
425
- atom: () => atom2,
426
- computed: () => computed,
427
- getValue: () => getValue,
428
- map: () => map2,
429
- onMount: () => onMount,
430
- onStart: () => onStart,
431
- onStop: () => onStop
432
- });
433
- var START_LISTENERS = /* @__PURE__ */ new WeakMap();
434
- var STOP_LISTENERS = /* @__PURE__ */ new WeakMap();
435
- function trigger(node2, map3) {
436
- const callbacks = map3.get(node2);
437
- if (callbacks) {
438
- for (const cb of callbacks) cb();
439
- }
440
- }
441
- function createStore(node2, extra = {}) {
442
- let listeners = 0;
443
- const store = {
444
- ...extra,
445
- get: () => getVal(node2),
446
- subscribe: (cb) => {
447
- if (listeners === 0) trigger(node2, START_LISTENERS);
448
- listeners++;
449
- const sub = node2.subscribe((msgs) => {
450
- for (const [t, v] of msgs) {
451
- if (t === DATA) cb(v);
452
- }
453
- });
454
- return () => {
455
- sub();
456
- listeners--;
457
- if (listeners === 0) trigger(node2, STOP_LISTENERS);
458
- };
459
- },
460
- listen: (cb) => {
461
- if (listeners === 0) trigger(node2, START_LISTENERS);
462
- listeners++;
463
- let initial = true;
464
- const sub = node2.subscribe((msgs) => {
465
- for (const [t, v] of msgs) {
466
- if (t === DATA) {
467
- if (initial) {
468
- initial = false;
469
- continue;
470
- }
471
- cb(v);
472
- }
473
- }
474
- });
475
- return () => {
476
- sub();
477
- listeners--;
478
- if (listeners === 0) trigger(node2, STOP_LISTENERS);
479
- };
480
- },
481
- _node: node2
482
- };
483
- return store;
484
- }
485
- function pull2(n) {
486
- let val = n.cache;
487
- let err;
488
- const unsub = n.subscribe((msgs) => {
489
- for (const [t, v] of msgs) {
490
- if (t === DATA) val = v;
491
- if (t === ERROR) err = v;
492
- }
493
- });
494
- unsub();
495
- if (err) throw err;
496
- return val;
497
- }
498
- function getVal(n) {
499
- if (n.status === "sentinel") {
500
- return pull2(n);
501
- }
502
- return n.cache;
503
- }
504
- function atom2(initial) {
505
- const n = state(initial, {
506
- resubscribable: true,
507
- resetOnTeardown: true
508
- });
509
- return createStore(n, {
510
- // `n.emit` routes through the framed pipeline: `bundle()` auto-
511
- // prefixes `[DIRTY]` (diamond-safe wave coordination) and the
512
- // node's `equals` (default `Object.is`) folds same-value writes
513
- // into `RESOLVED`. Matches nanostores' documented Object.is
514
- // dedup semantics without any custom check.
515
- set: (value) => n.emit(value)
516
- });
517
- }
518
- function computed(stores, fn) {
519
- const storeArray = Array.isArray(stores) ? stores : [stores];
520
- const depNodes = storeArray.map((s) => s._node);
521
- const n = dynamicNode(
522
- depNodes,
523
- (track) => {
524
- const vals = storeArray.map((s) => {
525
- const node2 = s._node;
526
- if (node2.status === "sentinel") {
527
- pull2(node2);
528
- }
529
- return track(node2);
530
- });
531
- return fn(...vals);
532
- },
533
- {
534
- resubscribable: true,
535
- resetOnTeardown: true,
536
- equals: Object.is
537
- }
538
- );
539
- return createStore(n);
540
- }
541
- function map2(initial) {
542
- const n = state(initial, {
543
- resubscribable: true,
544
- resetOnTeardown: true,
545
- equals: () => false
546
- });
547
- return createStore(n, {
548
- // `map`'s state node is configured with `equals: () => false`
549
- // above, so every `emit` produces DATA (even for same-key same-
550
- // value sets). The `emit` path is still required for diamond
551
- // coordination (`[DIRTY]` auto-prefix via `bundle()`).
552
- set: (value) => n.emit(value),
553
- setKey: (key, value) => {
554
- const current = getVal(n);
555
- n.emit({ ...current, [key]: value });
556
- }
557
- });
558
- }
559
- function getValue(store) {
560
- return store.get();
561
- }
562
- function onStart(store, cb) {
563
- const node2 = store._node;
564
- let callbacks = START_LISTENERS.get(node2);
565
- if (!callbacks) {
566
- callbacks = /* @__PURE__ */ new Set();
567
- START_LISTENERS.set(node2, callbacks);
568
- }
569
- callbacks.add(cb);
570
- }
571
- function onStop(store, cb) {
572
- const node2 = store._node;
573
- let callbacks = STOP_LISTENERS.get(node2);
574
- if (!callbacks) {
575
- callbacks = /* @__PURE__ */ new Set();
576
- STOP_LISTENERS.set(node2, callbacks);
577
- }
578
- callbacks.add(cb);
579
- }
580
- function onMount(store, cb) {
581
- onStart(store, () => {
582
- const stop = cb();
583
- if (typeof stop === "function") onStop(store, stop);
584
- });
585
- }
586
- function action(_store, _name, fn) {
587
- return (...args) => {
588
- let result;
589
- batch(() => {
590
- result = fn(...args);
591
- });
592
- return result;
593
- };
594
- }
595
-
596
- // src/compat/react/index.ts
597
- var react_exports = {};
598
- __export(react_exports, {
599
- useStore: () => useStore,
600
- useSubscribe: () => useSubscribe,
601
- useSubscribeRecord: () => useSubscribeRecord
602
- });
603
- import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
604
- function useSubscribe(node2) {
605
- return useSyncExternalStore(
606
- (onStoreChange) => {
607
- let disposed = false;
608
- const unsub = node2.subscribe(() => {
609
- if (!disposed) onStoreChange();
610
- });
611
- return () => {
612
- disposed = true;
613
- unsub();
614
- };
615
- },
616
- () => node2.cache,
617
- () => node2.cache
618
- // Server snapshot
619
- );
620
- }
621
- function useStore(node2) {
622
- const value = useSubscribe(node2);
623
- const setter = useCallback(
624
- (v) => {
625
- node2.down([[DIRTY], [DATA, v]]);
626
- },
627
- [node2]
628
- );
629
- return [value, setter];
630
- }
631
- function useSubscribeRecord(keysNode, factory) {
632
- const factoryRef = useRef(factory);
633
- factoryRef.current = factory;
634
- const store = useMemo(() => {
635
- const computeSnap = () => {
636
- const snap = {};
637
- const keys = keysNode.cache ?? [];
638
- for (const key of keys) {
639
- const nodes = factoryRef.current(key);
640
- const values = {};
641
- for (const field of Object.keys(nodes)) {
642
- values[field] = nodes[field].cache;
643
- }
644
- snap[key] = values;
645
- }
646
- return snap;
647
- };
648
- let currentSnapshot = computeSnap();
649
- return {
650
- subscribe: (onStoreChange) => {
651
- let disposed = false;
652
- let entrySubs = [];
653
- const cleanupEntries = () => {
654
- for (const unsub of entrySubs) unsub();
655
- entrySubs = [];
656
- };
657
- const sync = (nextKeys) => {
658
- cleanupEntries();
659
- for (const key of nextKeys) {
660
- const nodes = factoryRef.current(key);
661
- for (const field of Object.keys(nodes)) {
662
- const unsub = nodes[field].subscribe(() => {
663
- currentSnapshot = computeSnap();
664
- if (!disposed) onStoreChange();
665
- });
666
- entrySubs.push(unsub);
667
- }
668
- }
669
- currentSnapshot = computeSnap();
670
- if (!disposed) onStoreChange();
671
- };
672
- const keysUnsub = keysNode.subscribe((msgs) => {
673
- const hasSettled = msgs.some((m) => m[0] === DATA || m[0] === RESOLVED);
674
- if (!disposed && hasSettled) sync(keysNode.cache ?? []);
675
- });
676
- sync(keysNode.cache ?? []);
677
- return () => {
678
- disposed = true;
679
- keysUnsub();
680
- cleanupEntries();
681
- };
682
- },
683
- getSnapshot: () => currentSnapshot
684
- };
685
- }, [keysNode]);
686
- return useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
687
- }
688
-
689
- // src/compat/signals/index.ts
690
- var signals_exports = {};
691
- __export(signals_exports, {
692
- Signal: () => Signal
693
- });
694
- var trackingStack = [];
695
- function pull3(n) {
696
- let val = n.cache;
697
- const unsub = n.subscribe((msgs) => {
698
- for (const [t, v] of msgs) {
699
- if (t === DATA) val = v;
700
- }
701
- });
702
- unsub();
703
- return val;
704
- }
705
- var SignalState = class {
706
- /** @internal */
707
- _node;
708
- _equals;
709
- constructor(initial, opts) {
710
- this._equals = opts?.equals ?? Object.is;
711
- this._node = state(initial, {
712
- ...opts,
713
- resubscribable: true,
714
- resetOnTeardown: true
715
- });
716
- }
717
- get() {
718
- const tracker = trackingStack[trackingStack.length - 1];
719
- if (tracker) {
720
- if (this._node.status === "sentinel") {
721
- pull3(this._node);
722
- }
723
- return tracker(this._node);
724
- }
725
- if (this._node.status === "sentinel") {
726
- return pull3(this._node);
727
- }
728
- return this._node.cache;
729
- }
730
- set(value) {
731
- if (this._equals(this.get(), value)) return;
732
- batch(() => {
733
- this._node.down([[DIRTY], [DATA, value]]);
734
- });
735
- }
736
- };
737
- var SignalComputed = class {
738
- /** @internal */
739
- _node;
740
- constructor(computation, opts) {
741
- this._node = autoTrackNode(
742
- (track) => {
743
- trackingStack.push(track);
744
- try {
745
- return computation();
746
- } finally {
747
- trackingStack.pop();
748
- }
749
- },
750
- {
751
- ...opts,
752
- describeKind: "derived",
753
- resubscribable: true,
754
- resetOnTeardown: true
755
- }
756
- );
757
- }
758
- get() {
759
- const tracker = trackingStack[trackingStack.length - 1];
760
- if (tracker) {
761
- if (this._node.status === "sentinel") {
762
- pull3(this._node);
763
- }
764
- return tracker(this._node);
765
- }
766
- if (this._node.status === "sentinel") {
767
- return pull3(this._node);
768
- }
769
- return this._node.cache;
770
- }
771
- };
772
- var Signal = {
773
- State: SignalState,
774
- Computed: SignalComputed,
775
- /**
776
- * Subscribes to changes on a signal.
777
- * Returns an unsubscribe callback.
778
- *
779
- * @example
780
- * ```ts
781
- * const count = new Signal.State(0);
782
- * const unsub = Signal.sub(count, v => console.log(v));
783
- * ```
784
- */
785
- sub: (signal, callback) => {
786
- const handlers = typeof callback === "function" ? { data: callback, error: void 0, complete: void 0 } : callback;
787
- let initial = true;
788
- return signal._node.subscribe((msgs) => {
789
- for (const [t, v] of msgs) {
790
- if (t === DATA) {
791
- if (initial) {
792
- initial = false;
793
- continue;
794
- }
795
- handlers.data?.(v);
796
- }
797
- if (t === ERROR) handlers.error?.(v);
798
- if (t === COMPLETE) handlers.complete?.();
799
- }
800
- });
801
- }
802
- };
803
-
804
- // src/compat/solid/index.ts
805
- var solid_exports = {};
806
- __export(solid_exports, {
807
- useStore: () => useStore2,
808
- useSubscribe: () => useSubscribe2,
809
- useSubscribeRecord: () => useSubscribeRecord2
810
- });
811
- import { createSignal, getOwner, onCleanup } from "solid-js";
812
- function useSubscribe2(node2) {
813
- const [value, setValue] = createSignal(node2.cache, { equals: false });
814
- const unsub = node2.subscribe(() => {
815
- setValue(() => node2.cache);
816
- });
817
- if (getOwner()) {
818
- onCleanup(() => unsub());
819
- } else if (typeof console !== "undefined") {
820
- console.warn(
821
- "[graphrefly-ts] useSubscribe called outside a Solid reactive owner \u2014 subscription will not be auto-disposed."
822
- );
823
- }
824
- return value;
825
- }
826
- function useStore2(node2) {
827
- const value = useSubscribe2(node2);
828
- const setter = (v) => {
829
- node2.down([[DIRTY], [DATA, v]]);
830
- };
831
- return [value, setter];
832
- }
833
- function useSubscribeRecord2(keysNode, factory) {
834
- const [value, setValue] = createSignal({}, { equals: false });
835
- let entrySubs = [];
836
- const cleanupEntries = () => {
837
- for (const unsub of entrySubs) unsub();
838
- entrySubs = [];
839
- };
840
- const buildSnapshot = () => {
841
- const snap = {};
842
- for (const key of keysNode.cache ?? []) {
843
- const nodes = factory(key);
844
- const values = {};
845
- for (const field of Object.keys(nodes)) {
846
- values[field] = nodes[field].cache;
847
- }
848
- snap[key] = values;
849
- }
850
- return snap;
851
- };
852
- const sync = (nextKeys) => {
853
- cleanupEntries();
854
- for (const key of nextKeys) {
855
- const nodes = factory(key);
856
- for (const field of Object.keys(nodes)) {
857
- const unsub = nodes[field].subscribe(() => {
858
- setValue(() => buildSnapshot());
859
- });
860
- entrySubs.push(unsub);
861
- }
862
- }
863
- setValue(() => buildSnapshot());
864
- };
865
- const keysUnsub = keysNode.subscribe((msgs) => {
866
- if (msgs.some((m) => m[0] === DATA || m[0] === RESOLVED)) {
867
- sync(keysNode.cache ?? []);
868
- }
869
- });
870
- sync(keysNode.cache ?? []);
871
- if (getOwner()) {
872
- onCleanup(() => {
873
- keysUnsub();
874
- cleanupEntries();
875
- });
876
- } else if (typeof console !== "undefined") {
877
- console.warn(
878
- "[graphrefly-ts] useSubscribeRecord called outside a Solid reactive owner \u2014 subscription will not be auto-disposed."
879
- );
880
- }
881
- return value;
882
- }
883
-
884
- // src/compat/svelte/index.ts
885
- var svelte_exports = {};
886
- __export(svelte_exports, {
887
- useStore: () => useStore3,
888
- useSubscribe: () => useSubscribe3,
889
- useSubscribeRecord: () => useSubscribeRecord3
890
- });
891
- function useSubscribe3(node2) {
892
- return {
893
- subscribe(run) {
894
- const unsub = node2.subscribe(() => {
895
- run(node2.cache);
896
- });
897
- run(node2.cache);
898
- return unsub;
899
- }
900
- };
901
- }
902
- function useStore3(node2) {
903
- return {
904
- subscribe(run) {
905
- const unsub = node2.subscribe(() => {
906
- run(node2.cache);
907
- });
908
- run(node2.cache);
909
- return unsub;
910
- },
911
- set(value) {
912
- node2.down([[DIRTY], [DATA, value]]);
913
- },
914
- update(updater) {
915
- const next = updater(node2.cache);
916
- node2.down([[DIRTY], [DATA, next]]);
917
- }
918
- };
919
- }
920
- function useSubscribeRecord3(keysNode, factory) {
921
- return {
922
- subscribe(run) {
923
- let entrySubs = [];
924
- const cleanupEntries = () => {
925
- for (const unsub of entrySubs) unsub();
926
- entrySubs = [];
927
- };
928
- const buildSnapshot = () => {
929
- const snap = {};
930
- for (const key of keysNode.cache ?? []) {
931
- const nodes = factory(key);
932
- const values = {};
933
- for (const field of Object.keys(nodes)) {
934
- values[field] = nodes[field].cache;
935
- }
936
- snap[key] = values;
937
- }
938
- return snap;
939
- };
940
- const sync = (nextKeys) => {
941
- cleanupEntries();
942
- for (const key of nextKeys) {
943
- const nodes = factory(key);
944
- for (const field of Object.keys(nodes)) {
945
- const unsub = nodes[field].subscribe(() => {
946
- run(buildSnapshot());
947
- });
948
- entrySubs.push(unsub);
949
- }
950
- }
951
- run(buildSnapshot());
952
- };
953
- const keysUnsub = keysNode.subscribe((msgs) => {
954
- if (msgs.some((m) => m[0] === DATA || m[0] === RESOLVED)) {
955
- sync(keysNode.cache ?? []);
956
- }
957
- });
958
- sync(keysNode.cache ?? []);
959
- return () => {
960
- keysUnsub();
961
- cleanupEntries();
962
- };
963
- }
964
- };
965
- }
966
-
967
- // src/compat/vue/index.ts
968
- var vue_exports = {};
969
- __export(vue_exports, {
970
- useStore: () => useStore4,
971
- useSubscribe: () => useSubscribe4,
972
- useSubscribeRecord: () => useSubscribeRecord4
973
- });
291
+ } from "./chunk-PHOUUNK7.js";
974
292
  import {
975
- computed as computed2,
976
- getCurrentScope,
977
- isRef,
978
- onScopeDispose,
979
- readonly,
980
- shallowRef,
981
- watch
982
- } from "vue";
983
- function useSubscribe4(node2) {
984
- const ref = shallowRef(node2.cache);
985
- const unsub = node2.subscribe(() => {
986
- ref.value = node2.cache;
987
- });
988
- if (getCurrentScope()) {
989
- onScopeDispose(() => unsub());
990
- } else if (typeof console !== "undefined") {
991
- console.warn(
992
- "[graphrefly-ts] useSubscribe called outside a Vue scope \u2014 subscription will not be auto-disposed."
993
- );
994
- }
995
- return readonly(ref);
996
- }
997
- function useStore4(node2) {
998
- const inner = shallowRef(node2.cache);
999
- const unsub = node2.subscribe(() => {
1000
- inner.value = node2.cache;
1001
- });
1002
- if (getCurrentScope()) {
1003
- onScopeDispose(() => unsub());
1004
- } else if (typeof console !== "undefined") {
1005
- console.warn(
1006
- "[graphrefly-ts] useStore called outside a Vue scope \u2014 subscription will not be auto-disposed."
1007
- );
1008
- }
1009
- return computed2({
1010
- get: () => inner.value,
1011
- set: (v) => {
1012
- node2.down([[DIRTY], [DATA, v]]);
1013
- }
1014
- });
1015
- }
1016
- function useSubscribeRecord4(keys, factory) {
1017
- const result = shallowRef({});
1018
- const activeSubs = /* @__PURE__ */ new Map();
1019
- function flushResult() {
1020
- const snap = {};
1021
- for (const [key, entry] of activeSubs) {
1022
- snap[key] = { ...entry.values };
1023
- }
1024
- result.value = snap;
1025
- }
1026
- function sync(newKeys) {
1027
- for (const entry of activeSubs.values()) {
1028
- for (const unsub of entry.subs) unsub();
1029
- }
1030
- activeSubs.clear();
1031
- for (const key of newKeys) {
1032
- const nodes = factory(key);
1033
- const fields = Object.keys(nodes);
1034
- const values = {};
1035
- const subs = [];
1036
- for (const field of fields) {
1037
- const node2 = nodes[field];
1038
- values[field] = node2.cache;
1039
- const unsub = node2.subscribe(() => {
1040
- values[field] = node2.cache;
1041
- flushResult();
1042
- });
1043
- subs.push(unsub);
1044
- }
1045
- activeSubs.set(key, { subs, values });
1046
- }
1047
- const snap = {};
1048
- for (const [key, entry] of activeSubs) {
1049
- snap[key] = { ...entry.values };
1050
- }
1051
- result.value = snap;
1052
- }
1053
- const readKeys = () => {
1054
- const current = typeof keys === "function" ? keys() : isRef(keys) ? keys.value : keys;
1055
- return [...current ?? []];
1056
- };
1057
- watch(readKeys, (newKeys) => sync(newKeys ?? []), { immediate: true });
1058
- if (getCurrentScope()) {
1059
- onScopeDispose(() => {
1060
- for (const entry of activeSubs.values()) {
1061
- for (const unsub of entry.subs) unsub();
1062
- }
1063
- activeSubs.clear();
1064
- });
1065
- } else if (typeof console !== "undefined") {
1066
- console.warn(
1067
- "[graphrefly-ts] useSubscribeRecord called outside a Vue scope \u2014 subscription will not be auto-disposed."
1068
- );
1069
- }
1070
- return readonly(result);
1071
- }
1072
-
1073
- // src/compat/zustand/index.ts
1074
- var zustand_exports = {};
1075
- __export(zustand_exports, {
1076
- create: () => create
1077
- });
1078
- var alwaysDiffer = () => false;
1079
- function create(initializer) {
1080
- const g = new Graph("zustand");
1081
- const s = state(void 0, {
1082
- name: "state",
1083
- equals: alwaysDiffer
1084
- });
1085
- g.add("state", s);
1086
- const getState = () => s.cache;
1087
- const setState = (partial, replace) => {
1088
- const prev = s.cache;
1089
- const next = typeof partial === "function" ? partial(prev) : partial;
1090
- s.emit(replace ? next : { ...prev, ...next });
1091
- };
1092
- const api = {
1093
- getState,
1094
- setState,
1095
- getInitialState: () => initialValue,
1096
- subscribe: (listener) => {
1097
- let initial = true;
1098
- let prev = s.cache;
1099
- return s.subscribe((msgs) => {
1100
- for (const [t, v] of msgs) {
1101
- if (t === DATA) {
1102
- if (initial) {
1103
- initial = false;
1104
- continue;
1105
- }
1106
- listener(v, prev);
1107
- prev = v;
1108
- }
1109
- }
1110
- });
1111
- },
1112
- destroy: g.destroy.bind(g)
1113
- };
1114
- const initialValue = initializer(setState, getState, api);
1115
- s.emit(initialValue);
1116
- return Object.assign(g, api);
1117
- }
293
+ COMPLETE,
294
+ COMPLETE_MSG,
295
+ COMPLETE_ONLY_BATCH,
296
+ DATA,
297
+ DIRTY,
298
+ DIRTY_MSG,
299
+ DIRTY_ONLY_BATCH,
300
+ ERROR,
301
+ INVALIDATE,
302
+ INVALIDATE_MSG,
303
+ INVALIDATE_ONLY_BATCH,
304
+ PAUSE,
305
+ RESOLVED,
306
+ RESOLVED_MSG,
307
+ RESOLVED_ONLY_BATCH,
308
+ RESUME,
309
+ START,
310
+ START_MSG,
311
+ TEARDOWN,
312
+ TEARDOWN_MSG,
313
+ TEARDOWN_ONLY_BATCH,
314
+ __export
315
+ } from "./chunk-SX52TAR4.js";
1118
316
 
1119
317
  // src/patterns/index.ts
1120
318
  var patterns_exports = {};
1121
319
  __export(patterns_exports, {
320
+ SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
321
+ SurfaceError: () => SurfaceError,
322
+ accountability: () => audit_exports,
1122
323
  ai: () => ai_exports,
324
+ asSurfaceError: () => asSurfaceError,
1123
325
  cqrs: () => cqrs_exports,
326
+ createGraph: () => createGraph,
327
+ deleteSnapshot: () => deleteSnapshot,
1124
328
  demoShell: () => demo_shell_exports,
329
+ diffSnapshots: () => diffSnapshots,
1125
330
  domainTemplates: () => domain_templates_exports,
1126
331
  graphspec: () => graphspec_exports,
332
+ guarded: () => guarded_execution_exports,
1127
333
  harness: () => harness_exports,
1128
334
  layout: () => reactive_layout_exports,
335
+ lens: () => lens_exports,
336
+ listSnapshots: () => listSnapshots,
1129
337
  memory: () => memory_exports,
1130
338
  messaging: () => messaging_exports,
1131
339
  orchestration: () => orchestration_exports,
1132
- reduction: () => reduction_exports
340
+ reduction: () => reduction_exports,
341
+ resilientPipeline: () => resilient_pipeline_exports,
342
+ restoreSnapshot: () => restoreSnapshot,
343
+ runReduction: () => runReduction,
344
+ saveSnapshot: () => saveSnapshot,
345
+ surface: () => surface_exports
1133
346
  });
1134
347
 
1135
348
  // src/patterns/ai.ts
@@ -4167,308 +3380,418 @@ async function suggestStrategy(graph, problem, adapter, opts) {
4167
3380
  };
4168
3381
  }
4169
3382
 
4170
- // src/patterns/demo-shell.ts
4171
- var demo_shell_exports = {};
4172
- __export(demo_shell_exports, {
4173
- demoShell: () => demoShell
3383
+ // src/patterns/audit.ts
3384
+ var audit_exports = {};
3385
+ __export(audit_exports, {
3386
+ AuditTrailGraph: () => AuditTrailGraph,
3387
+ PolicyEnforcerGraph: () => PolicyEnforcerGraph,
3388
+ auditTrail: () => auditTrail,
3389
+ complianceSnapshot: () => complianceSnapshot,
3390
+ policyEnforcer: () => policyEnforcer,
3391
+ reactiveExplainPath: () => reactiveExplainPath
4174
3392
  });
4175
- function clamp01(v) {
4176
- return Math.max(0, Math.min(1, v));
4177
- }
4178
- function demoShell(opts) {
4179
- const mainRatioInit = clamp01(opts?.mainRatio ?? 0.65);
4180
- const sideSplitInit = clamp01(opts?.sideSplit ?? 0.5);
4181
- const viewportInit = Math.max(0, opts?.viewportWidth ?? 1280);
4182
- const registry = opts?.nodeRegistry ?? /* @__PURE__ */ new Map();
4183
- const adapter = opts?.adapter ?? null;
4184
- const layoutFont = opts?.layoutFont ?? "14px monospace";
4185
- const onHighlight = opts?.onHighlight;
4186
- const g = new Graph("demo-shell");
4187
- const paneMainRatio = state(mainRatioInit, { name: "pane/main-ratio" });
4188
- const paneSideSplit = state(sideSplitInit, { name: "pane/side-split" });
4189
- const paneFullscreen = state(null, {
4190
- name: "pane/fullscreen"
4191
- });
4192
- const viewportWidth = state(viewportInit, { name: "viewport/width" });
4193
- g.add("pane/main-ratio", paneMainRatio);
4194
- g.add("pane/side-split", paneSideSplit);
4195
- g.add("pane/fullscreen", paneFullscreen);
4196
- g.add("viewport/width", viewportWidth);
4197
- const paneMainWidth = derived(
4198
- [paneMainRatio, viewportWidth, paneFullscreen],
4199
- ([ratio, vw, fs]) => {
4200
- const r = ratio;
4201
- const w = vw;
4202
- const fullscreen = fs;
4203
- if (fullscreen === "main") return w;
4204
- if (fullscreen === "graph" || fullscreen === "code") return 0;
4205
- return Math.round(w * r);
4206
- },
4207
- { name: "pane/main-width" }
4208
- );
4209
- const paneSideWidth = derived(
4210
- [paneMainWidth, viewportWidth, paneFullscreen],
4211
- ([main, vw, fs]) => {
4212
- const fullscreen = fs;
4213
- const w = vw;
4214
- if (fullscreen === "main") return 0;
4215
- if (fullscreen === "graph" || fullscreen === "code") return w;
4216
- return w - main;
4217
- },
4218
- { name: "pane/side-width" }
4219
- );
4220
- const paneGraphHeight = derived(
4221
- [paneSideSplit, paneFullscreen],
4222
- ([split, fs]) => {
4223
- const fullscreen = fs;
4224
- if (fullscreen === "graph") return 1;
4225
- if (fullscreen === "code") return 0;
4226
- if (fullscreen === "main") return 0;
4227
- return clamp01(split);
4228
- },
4229
- { name: "pane/graph-height-ratio" }
4230
- );
4231
- const paneCodeHeight = derived(
4232
- [paneGraphHeight, paneFullscreen],
4233
- ([graphH, fs]) => {
4234
- const fullscreen = fs;
4235
- if (fullscreen === "code") return 1;
4236
- if (fullscreen === "graph" || fullscreen === "main") return 0;
4237
- return 1 - graphH;
4238
- },
4239
- { name: "pane/code-height-ratio" }
4240
- );
4241
- g.add("pane/main-width", paneMainWidth);
4242
- g.add("pane/side-width", paneSideWidth);
4243
- g.add("pane/graph-height-ratio", paneGraphHeight);
4244
- g.add("pane/code-height-ratio", paneCodeHeight);
4245
- const demoGraphRef = state(null, {
4246
- name: "demo/graph-ref"
4247
- });
4248
- const demoGraphTick = state(0, { name: "demo/graph-tick" });
4249
- g.add("demo/graph-ref", demoGraphRef);
4250
- g.add("demo/graph-tick", demoGraphTick);
4251
- const graphMermaid = derived(
4252
- [demoGraphRef, demoGraphTick],
4253
- ([ref, _tick]) => {
4254
- const demo = ref;
4255
- if (!demo) return "";
4256
- return demo.describe({ format: "mermaid" });
4257
- },
4258
- { name: "graph/mermaid" }
4259
- );
4260
- const graphDescribe = derived(
4261
- [demoGraphRef, demoGraphTick],
4262
- ([ref, _tick]) => {
4263
- const demo = ref;
4264
- if (!demo) return null;
4265
- const { expand: _, ...snapshot } = demo.describe({ detail: "standard" });
4266
- return snapshot;
4267
- },
4268
- { name: "graph/describe" }
4269
- );
4270
- g.add("graph/mermaid", graphMermaid);
4271
- g.add("graph/describe", graphDescribe);
4272
- const hoverTarget = state(null, { name: "hover/target" });
4273
- g.add("hover/target", hoverTarget);
4274
- const highlightCodeScroll = derived(
4275
- [hoverTarget],
4276
- ([target]) => {
4277
- const t = target;
4278
- if (!t) return null;
4279
- const entry = registry.get(t.id);
4280
- return entry ? entry.codeLine : null;
4281
- },
4282
- { name: "highlight/code-scroll" }
4283
- );
4284
- const highlightVisual = derived(
4285
- [hoverTarget],
4286
- ([target]) => {
4287
- const t = target;
4288
- if (!t) return null;
4289
- const entry = registry.get(t.id);
4290
- return entry ? entry.visualSelector : null;
4291
- },
4292
- { name: "highlight/visual" }
4293
- );
4294
- const highlightGraph = derived(
4295
- [hoverTarget],
4296
- ([target]) => {
4297
- const t = target;
4298
- if (!t) return null;
4299
- return t.id;
4300
- },
4301
- { name: "highlight/graph" }
4302
- );
4303
- g.add("highlight/code-scroll", highlightCodeScroll);
4304
- g.add("highlight/visual", highlightVisual);
4305
- g.add("highlight/graph", highlightGraph);
4306
- if (onHighlight?.codeScroll) {
4307
- const cb = onHighlight.codeScroll;
4308
- const applyCodeScroll = effect([highlightCodeScroll], ([line]) => {
4309
- cb(line);
3393
+ function auditMeta(kind, extra) {
3394
+ return domainMeta("audit", kind, extra);
3395
+ }
3396
+ var DEFAULT_INCLUDE_TYPES = /* @__PURE__ */ new Set([
3397
+ "data",
3398
+ "error",
3399
+ "complete",
3400
+ "teardown"
3401
+ ]);
3402
+ var AuditTrailGraph = class extends Graph {
3403
+ entries;
3404
+ count;
3405
+ _log;
3406
+ _target;
3407
+ constructor(target, opts) {
3408
+ super(opts.name ?? `${target.name}_audit`, opts.graph);
3409
+ this._target = target;
3410
+ this._log = reactiveLog([], {
3411
+ name: "entries",
3412
+ ...opts.maxSize != null ? { maxSize: opts.maxSize } : {}
4310
3413
  });
4311
- g.add("highlight/apply-code-scroll", applyCodeScroll);
3414
+ this.entries = this._log.entries;
3415
+ this.add("entries", this.entries);
3416
+ this.count = derived(
3417
+ [this.entries],
3418
+ ([snapshot]) => snapshot.length,
3419
+ { name: "count", describeKind: "derived", meta: auditMeta("count") }
3420
+ );
3421
+ this.add("count", this.count);
3422
+ this.addDisposer(keepalive(this.count));
3423
+ const includeTypes = opts.includeTypes != null ? new Set(opts.includeTypes) : DEFAULT_INCLUDE_TYPES;
3424
+ const filter2 = opts.filter;
3425
+ let seq = 0;
3426
+ const handle = target.observe({ timeline: true, structured: true });
3427
+ const offEvent = handle.onEvent((event) => {
3428
+ if (event.type === "derived") return;
3429
+ const type = event.type;
3430
+ if (!includeTypes.has(type)) return;
3431
+ const path = event.path ?? "";
3432
+ const entry = {
3433
+ seq: seq++,
3434
+ timestamp_ns: event.timestamp_ns ?? monotonicNs(),
3435
+ wall_clock_ns: wallClockNs(),
3436
+ path,
3437
+ type
3438
+ };
3439
+ const node2 = path ? safeNode(target, path) : void 0;
3440
+ const lastMutation = node2?.lastMutation;
3441
+ if (lastMutation != null) entry.actor = lastMutation.actor;
3442
+ if (type === "data") entry.value = event.data;
3443
+ if (type === "error") entry.error = event.data;
3444
+ const reason = path ? safeAnnotation(target, path) : void 0;
3445
+ if (reason != null) entry.reason = reason;
3446
+ if (filter2 != null && !filter2(entry)) return;
3447
+ this._log.append(entry);
3448
+ });
3449
+ this.addDisposer(() => {
3450
+ offEvent();
3451
+ handle.dispose();
3452
+ });
3453
+ this.addDisposer(() => this._log.disposeAllViews());
3454
+ }
3455
+ /** All entries currently in the ring (snapshot). */
3456
+ all() {
3457
+ return this.entries.cache ?? [];
3458
+ }
3459
+ /** Entries matching `path`. Order preserved. */
3460
+ byNode(path) {
3461
+ return this.all().filter((e) => e.path === path);
3462
+ }
3463
+ /** Entries whose `actor.id` matches. Use `byActorType` for type filtering. */
3464
+ byActor(actorId) {
3465
+ return this.all().filter((e) => e.actor?.id === actorId);
3466
+ }
3467
+ /** Entries whose `actor.type` matches (e.g. `"llm"`, `"human"`). */
3468
+ byActorType(type) {
3469
+ return this.all().filter((e) => e.actor?.type === type);
3470
+ }
3471
+ /**
3472
+ * Entries with `timestamp_ns` in `[start_ns, end_ns)` (end exclusive).
3473
+ * Omit `end_ns` to query open-ended.
3474
+ */
3475
+ byTimeRange(start_ns, end_ns) {
3476
+ return this.all().filter((e) => {
3477
+ if (e.timestamp_ns < start_ns) return false;
3478
+ if (end_ns != null && e.timestamp_ns >= end_ns) return false;
3479
+ return true;
3480
+ });
3481
+ }
3482
+ /** Reference to the audited graph (escape hatch for tooling). */
3483
+ get target() {
3484
+ return this._target;
3485
+ }
3486
+ };
3487
+ function auditTrail(target, opts = {}) {
3488
+ return new AuditTrailGraph(target, opts);
3489
+ }
3490
+ var PolicyEnforcerGraph = class extends Graph {
3491
+ policies;
3492
+ violations;
3493
+ violationCount;
3494
+ _target;
3495
+ _mode;
3496
+ _currentGuard;
3497
+ constructor(target, policies, opts) {
3498
+ super(opts.name ?? `${target.name}_policy`, opts.graph);
3499
+ this._target = target;
3500
+ this._mode = opts.mode ?? "audit";
3501
+ const policiesNode = isNode(policies) ? policies : state(policies, { name: "policies" });
3502
+ this.policies = policiesNode;
3503
+ this.add("policies", this.policies);
3504
+ this.violations = new TopicGraph("violations", {
3505
+ retainedLimit: opts.violationsLimit ?? 1e3
3506
+ });
3507
+ this.mount("violations", this.violations);
3508
+ this.violationCount = derived(
3509
+ [this.violations.events],
3510
+ ([snapshot]) => snapshot.length,
3511
+ {
3512
+ name: "violationCount",
3513
+ describeKind: "derived",
3514
+ meta: auditMeta("policy_violation_count")
3515
+ }
3516
+ );
3517
+ this.add("violationCount", this.violationCount);
3518
+ this.addDisposer(keepalive(this.violationCount));
3519
+ const initialRules = policiesNode.cache ?? [];
3520
+ let latestRules = initialRules;
3521
+ this._currentGuard = policyFromRules(latestRules);
3522
+ const offPolicies = policiesNode.subscribe((msgs) => {
3523
+ for (const m of msgs) {
3524
+ if (m[0] === DATA) {
3525
+ latestRules = m[1] ?? [];
3526
+ this._currentGuard = policyFromRules(latestRules);
3527
+ }
3528
+ }
3529
+ });
3530
+ this.addDisposer(offPolicies);
3531
+ const paths = opts.paths != null ? [...opts.paths] : collectPaths(target);
3532
+ if (this._mode === "enforce") {
3533
+ const restorers = /* @__PURE__ */ new Map();
3534
+ const wrapAndPush = (path) => {
3535
+ if (restorers.has(path)) return;
3536
+ const node2 = safeNode(target, path);
3537
+ if (!(node2 instanceof NodeImpl)) return;
3538
+ const pathGuard = (actor, action) => {
3539
+ const ok = this._currentGuard(actor, action);
3540
+ if (!ok) {
3541
+ this._publishViolation(actor, action, path, "blocked");
3542
+ }
3543
+ return ok;
3544
+ };
3545
+ restorers.set(path, node2._pushGuard(pathGuard));
3546
+ };
3547
+ for (const path of paths) wrapAndPush(path);
3548
+ if (opts.paths == null) {
3549
+ const offTopology = watchTopologyTree(target, (event, emitter, prefix) => {
3550
+ if (event.kind === "added") {
3551
+ if (event.nodeKind === "node") {
3552
+ wrapAndPush(`${prefix}${event.name}`);
3553
+ } else {
3554
+ const child = emitter._mounts.get(event.name);
3555
+ if (!(child instanceof Graph)) return;
3556
+ const mountPrefix = `${prefix}${event.name}::`;
3557
+ const localPaths = collectPaths(child);
3558
+ for (const localPath of localPaths) {
3559
+ wrapAndPush(
3560
+ localPath === "" ? `${prefix}${event.name}` : `${mountPrefix}${localPath}`
3561
+ );
3562
+ }
3563
+ }
3564
+ } else if (event.kind === "removed") {
3565
+ if (event.nodeKind === "node") {
3566
+ const qp = `${prefix}${event.name}`;
3567
+ const r = restorers.get(qp);
3568
+ if (r != null) {
3569
+ r();
3570
+ restorers.delete(qp);
3571
+ }
3572
+ } else {
3573
+ const mountQp = `${prefix}${event.name}`;
3574
+ const mountPrefix = `${mountQp}::`;
3575
+ for (const [p, r] of restorers) {
3576
+ if (p === mountQp || p.startsWith(mountPrefix)) {
3577
+ r();
3578
+ restorers.delete(p);
3579
+ }
3580
+ }
3581
+ }
3582
+ }
3583
+ });
3584
+ this.addDisposer(offTopology);
3585
+ } else {
3586
+ const offCleanup = target.topology.subscribe((msgs) => {
3587
+ for (const m of msgs) {
3588
+ if (m[0] !== DATA) continue;
3589
+ const event = m[1];
3590
+ if (event.kind !== "removed" || event.nodeKind !== "node") continue;
3591
+ const r = restorers.get(event.name);
3592
+ if (r != null) {
3593
+ r();
3594
+ restorers.delete(event.name);
3595
+ }
3596
+ }
3597
+ });
3598
+ this.addDisposer(offCleanup);
3599
+ }
3600
+ this.addDisposer(() => {
3601
+ for (const r of restorers.values()) r();
3602
+ restorers.clear();
3603
+ });
3604
+ } else {
3605
+ const handle = target.observe({ timeline: true, structured: true });
3606
+ const off = handle.onEvent((event) => {
3607
+ if (event.type !== "data" && event.type !== "error") return;
3608
+ const path = event.path ?? "";
3609
+ if (!path) return;
3610
+ if (opts.paths != null && !opts.paths.includes(path)) return;
3611
+ const node2 = safeNode(target, path);
3612
+ const lastMutation = node2?.lastMutation;
3613
+ if (lastMutation == null) return;
3614
+ const action = "write";
3615
+ if (this._currentGuard(lastMutation.actor, action)) return;
3616
+ this._publishViolation(lastMutation.actor, action, path, "observed");
3617
+ });
3618
+ this.addDisposer(() => {
3619
+ off();
3620
+ handle.dispose();
3621
+ });
3622
+ }
4312
3623
  }
4313
- if (onHighlight?.visual) {
4314
- const cb = onHighlight.visual;
4315
- const applyVisual = effect([highlightVisual], ([selector]) => {
4316
- cb(selector);
3624
+ _publishViolation(actor, action, path, result) {
3625
+ this.violations.publish({
3626
+ timestamp_ns: monotonicNs(),
3627
+ wall_clock_ns: wallClockNs(),
3628
+ path,
3629
+ actor,
3630
+ action,
3631
+ mode: this._mode,
3632
+ result
4317
3633
  });
4318
- g.add("highlight/apply-visual", applyVisual);
4319
3634
  }
4320
- if (onHighlight?.graph) {
4321
- const cb = onHighlight.graph;
4322
- const applyGraph = effect([highlightGraph], ([nodeId]) => {
4323
- cb(nodeId);
4324
- });
4325
- g.add("highlight/apply-graph", applyGraph);
3635
+ /** Snapshot of recorded violations. */
3636
+ all() {
3637
+ return this.violations.retained();
3638
+ }
3639
+ get mode() {
3640
+ return this._mode;
4326
3641
  }
4327
- const inspectSelected = state(null, {
4328
- name: "inspect/selected-node"
3642
+ get target() {
3643
+ return this._target;
3644
+ }
3645
+ };
3646
+ function policyEnforcer(target, policies, opts = {}) {
3647
+ return new PolicyEnforcerGraph(target, policies, opts);
3648
+ }
3649
+ function reactiveExplainPath(target, from, to, opts) {
3650
+ let v = 0;
3651
+ const version2 = state(v, { name: "explain_version" });
3652
+ const handle = target.observe({ timeline: true, structured: true });
3653
+ const off = handle.onEvent((event) => {
3654
+ const t = event.type;
3655
+ if (t !== "data" && t !== "error" && t !== "complete" && t !== "teardown") return;
3656
+ v += 1;
3657
+ version2.emit(v);
4329
3658
  });
4330
- g.add("inspect/selected-node", inspectSelected);
4331
- const standardFields = resolveDescribeFields("standard");
4332
- const inspectNodeDetail = derived(
4333
- [inspectSelected, demoGraphRef, demoGraphTick],
4334
- ([path, ref, _tick]) => {
4335
- const demo = ref;
4336
- const p = path;
4337
- if (!demo || !p) return null;
4338
- try {
4339
- const nd = demo.resolve(p);
4340
- const nodeDesc = describeNode(nd, standardFields);
4341
- return { path: p, ...nodeDesc, value: nd.cache };
4342
- } catch {
4343
- return null;
3659
+ const explainOpts = {
3660
+ ...opts?.maxDepth != null ? { maxDepth: opts.maxDepth } : {},
3661
+ ...opts?.findCycle === true ? { findCycle: true } : {}
3662
+ };
3663
+ const node2 = derived([version2], () => target.explain(from, to, explainOpts), {
3664
+ name: opts?.name ?? "explain",
3665
+ describeKind: "derived",
3666
+ equals: (a, b) => a.found === b.found && a.reason === b.reason && a.steps.length === b.steps.length && causalStepsEqual(a.steps, b.steps),
3667
+ meta: auditMeta("explain_path", { from, to })
3668
+ });
3669
+ const stopKeepalive = keepalive(node2);
3670
+ return {
3671
+ node: node2,
3672
+ dispose() {
3673
+ off();
3674
+ handle.dispose();
3675
+ stopKeepalive();
3676
+ }
3677
+ };
3678
+ }
3679
+ function causalStepsEqual(a, b) {
3680
+ for (let i = 0; i < a.length; i++) {
3681
+ const x = a[i];
3682
+ const y = b[i];
3683
+ if (x.path !== y.path) return false;
3684
+ if (x.type !== y.type) return false;
3685
+ if (x.status !== y.status) return false;
3686
+ if (x.hop !== y.hop) return false;
3687
+ if (x.dep_index !== y.dep_index) return false;
3688
+ if (x.reason !== y.reason) return false;
3689
+ if (x.value !== y.value) return false;
3690
+ if (x.lastMutation !== y.lastMutation) return false;
3691
+ const xv = x.v;
3692
+ const yv = y.v;
3693
+ if (xv !== yv) {
3694
+ if (xv == null || yv == null) return false;
3695
+ if (xv.id !== yv.id || xv.version !== yv.version) return false;
3696
+ }
3697
+ }
3698
+ return true;
3699
+ }
3700
+ function complianceSnapshot(target, opts = {}) {
3701
+ const result = {
3702
+ format_version: 1,
3703
+ timestamp_ns: monotonicNs(),
3704
+ wall_clock_ns: wallClockNs(),
3705
+ graph: target.snapshot()
3706
+ };
3707
+ if (opts.actor != null) result.actor = opts.actor;
3708
+ if (opts.audit != null) {
3709
+ const entries = [...opts.audit.all()];
3710
+ result.audit = { count: entries.length, entries };
3711
+ }
3712
+ if (opts.policies != null) {
3713
+ const rules = opts.policies.policies.cache ?? [];
3714
+ result.policies = {
3715
+ mode: opts.policies.mode,
3716
+ rules,
3717
+ violations: [...opts.policies.all()]
3718
+ };
3719
+ }
3720
+ const fingerprint = computeFingerprint(result);
3721
+ return { ...result, fingerprint };
3722
+ }
3723
+ function isNode(x) {
3724
+ return typeof x === "object" && x !== null && "subscribe" in x;
3725
+ }
3726
+ function safeNode(target, path) {
3727
+ try {
3728
+ return target.node(path);
3729
+ } catch {
3730
+ return void 0;
3731
+ }
3732
+ }
3733
+ function safeAnnotation(target, path) {
3734
+ try {
3735
+ return target.annotation(path);
3736
+ } catch {
3737
+ return void 0;
3738
+ }
3739
+ }
3740
+ function collectPaths(target) {
3741
+ const described = target.describe({ detail: "minimal" });
3742
+ return Object.keys(described.nodes);
3743
+ }
3744
+ function computeFingerprint(value) {
3745
+ return defaultHash(JSON.stringify(canonicalize(value)));
3746
+ }
3747
+ function canonicalize(value) {
3748
+ const stack = /* @__PURE__ */ new Set();
3749
+ const walk = (v) => {
3750
+ if (v === void 0) return { __undefined: true };
3751
+ if (v === null) return null;
3752
+ const t = typeof v;
3753
+ if (t === "bigint") return { __bigint: v.toString() };
3754
+ if (t !== "object") return v;
3755
+ const obj = v;
3756
+ if (stack.has(obj)) return { __circular: true };
3757
+ stack.add(obj);
3758
+ try {
3759
+ if (Array.isArray(obj)) {
3760
+ return obj.map(walk);
4344
3761
  }
4345
- },
4346
- { name: "inspect/node-detail" }
4347
- );
4348
- const inspectTraceLog = derived(
4349
- [demoGraphRef, demoGraphTick],
4350
- ([ref, _tick]) => {
4351
- const demo = ref;
4352
- if (!demo) return [];
4353
- return demo.trace();
4354
- },
4355
- { name: "inspect/trace-log" }
4356
- );
4357
- g.add("inspect/node-detail", inspectNodeDetail);
4358
- g.add("inspect/trace-log", inspectTraceLog);
4359
- const metaDebug = state(false, { name: "meta/debug" });
4360
- g.add("meta/debug", metaDebug);
4361
- const metaShellMermaid = derived(
4362
- [metaDebug, demoGraphTick],
4363
- ([debug, _tick]) => {
4364
- if (!debug) return "";
4365
- return g.describe({ format: "mermaid" });
4366
- },
4367
- { name: "meta/shell-mermaid" }
4368
- );
4369
- g.add("meta/shell-mermaid", metaShellMermaid);
4370
- const codeTextNode = state("", { name: "layout/code-text" });
4371
- g.add("layout/code-text", codeTextNode);
4372
- if (adapter) {
4373
- const measureCache = /* @__PURE__ */ new Map();
4374
- const graphLabels = derived(
4375
- [graphDescribe],
4376
- ([desc]) => {
4377
- const d = desc;
4378
- if (!d) return /* @__PURE__ */ new Map();
4379
- const result = /* @__PURE__ */ new Map();
4380
- for (const [name] of Object.entries(d.nodes)) {
4381
- const segments = analyzeAndMeasure(name, layoutFont, adapter, measureCache);
4382
- const lb = computeLineBreaks(segments, Infinity, adapter, layoutFont, measureCache);
4383
- const width = lb.lines.reduce((max, l) => Math.max(max, l.width), 0);
4384
- const height = lb.lineCount * 20;
4385
- result.set(name, { width, height });
4386
- }
4387
- return result;
4388
- },
4389
- {
4390
- name: "layout/graph-labels",
4391
- equals: (a, b) => {
4392
- if (a === b) return true;
4393
- const ma = a;
4394
- const mb = b;
4395
- if (ma.size !== mb.size) return false;
4396
- for (const [k, v] of ma) {
4397
- const bv = mb.get(k);
4398
- if (!bv || bv.width !== v.width || bv.height !== v.height) return false;
4399
- }
4400
- return true;
4401
- }
3762
+ if (obj instanceof Date) {
3763
+ return { __date: obj.toISOString() };
4402
3764
  }
4403
- );
4404
- const codeLines = derived(
4405
- [codeTextNode, paneSideWidth],
4406
- ([text, sideW]) => {
4407
- const t = text;
4408
- if (!t) return { lineCount: 0, lines: [] };
4409
- const segments = analyzeAndMeasure(t, layoutFont, adapter, measureCache);
4410
- const maxW = sideW - 40;
4411
- return computeLineBreaks(segments, Math.max(100, maxW), adapter, layoutFont, measureCache);
4412
- },
4413
- { name: "layout/code-lines" }
4414
- );
4415
- const sideWidthHint = derived(
4416
- [graphLabels],
4417
- ([labels]) => {
4418
- const m = labels;
4419
- if (m.size === 0) return 200;
4420
- let maxW = 0;
4421
- for (const { width } of m.values()) {
4422
- if (width > maxW) maxW = width;
4423
- }
4424
- return Math.max(200, Math.round(maxW + 80));
4425
- },
4426
- { name: "layout/side-width-hint" }
4427
- );
4428
- g.add("layout/graph-labels", graphLabels);
4429
- g.add("layout/code-lines", codeLines);
4430
- g.add("layout/side-width-hint", sideWidthHint);
4431
- }
4432
- let tickCounter = 0;
4433
- return {
4434
- graph: g,
4435
- setMainRatio(ratio) {
4436
- g.set("pane/main-ratio", clamp01(ratio));
4437
- },
4438
- setSideSplit(ratio) {
4439
- g.set("pane/side-split", clamp01(ratio));
4440
- },
4441
- setFullscreen(pane) {
4442
- g.set("pane/fullscreen", pane);
4443
- },
4444
- setViewportWidth(width) {
4445
- g.set("viewport/width", Math.max(0, width));
4446
- },
4447
- setHoverTarget(target) {
4448
- g.set("hover/target", target);
4449
- },
4450
- setDemoGraph(demo) {
4451
- g.set("demo/graph-ref", demo);
4452
- },
4453
- bumpGraphTick() {
4454
- g.set("demo/graph-tick", ++tickCounter);
4455
- },
4456
- selectNode(path) {
4457
- g.set("inspect/selected-node", path);
4458
- },
4459
- setMetaDebug(on) {
4460
- g.set("meta/debug", on);
4461
- },
4462
- setCodeText(text) {
4463
- g.set("layout/code-text", text);
4464
- },
4465
- batch(fn) {
4466
- batch(fn);
4467
- },
4468
- destroy() {
4469
- g.destroy();
3765
+ if (obj instanceof RegExp) {
3766
+ return { __regexp: { source: obj.source, flags: obj.flags } };
3767
+ }
3768
+ if (obj instanceof Map) {
3769
+ const entries = [...obj.entries()].map(([k, mv]) => [
3770
+ walk(k),
3771
+ walk(mv)
3772
+ ]);
3773
+ return { __map: entries };
3774
+ }
3775
+ if (obj instanceof Set) {
3776
+ const items = [...obj].map(walk);
3777
+ return { __set: items };
3778
+ }
3779
+ if (ArrayBuffer.isView(obj)) {
3780
+ const ta = obj;
3781
+ const arr = new Array(ta.length);
3782
+ for (let i = 0; i < ta.length; i++) arr[i] = ta[i] ?? 0;
3783
+ return { __typed_array: { ctor: obj.constructor.name, data: arr } };
3784
+ }
3785
+ const out = {};
3786
+ for (const k of Object.keys(obj).sort()) {
3787
+ out[k] = walk(obj[k]);
3788
+ }
3789
+ return out;
3790
+ } finally {
3791
+ stack.delete(obj);
4470
3792
  }
4471
3793
  };
3794
+ return walk(value);
4472
3795
  }
4473
3796
 
4474
3797
  // src/patterns/domain-templates.ts
@@ -6301,6 +5624,65 @@ ${validation.errors.join("\n")}`);
6301
5624
  return parsed;
6302
5625
  }
6303
5626
 
5627
+ // src/patterns/guarded-execution.ts
5628
+ var guarded_execution_exports = {};
5629
+ __export(guarded_execution_exports, {
5630
+ GuardedExecutionGraph: () => GuardedExecutionGraph,
5631
+ guardedExecution: () => guardedExecution
5632
+ });
5633
+ var GuardedExecutionGraph = class extends Graph {
5634
+ enforcer;
5635
+ violations;
5636
+ _target;
5637
+ _defaultActor;
5638
+ constructor(target, opts) {
5639
+ super(opts.name ?? `${target.name}_guarded`, opts.graph);
5640
+ this._target = target;
5641
+ this._defaultActor = opts.actor;
5642
+ const enforcerOpts = {
5643
+ mode: opts.mode ?? "enforce",
5644
+ name: "enforcer"
5645
+ };
5646
+ if (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;
5647
+ this.enforcer = policyEnforcer(target, opts.policies, enforcerOpts);
5648
+ this.violations = this.enforcer.violations;
5649
+ this.mount("enforcer", this.enforcer);
5650
+ }
5651
+ /**
5652
+ * Describe the **target** graph scoped to the configured actor. Returns
5653
+ * only nodes the actor is permitted to see (via the target's node guards
5654
+ * filtering `describe()` via `actor`).
5655
+ *
5656
+ * Pass `{actor}` in opts to override the configured actor for this call.
5657
+ * Pass any standard {@link GraphDescribeOptions} fields (`detail`,
5658
+ * `fields`, `filter`) — they apply to the target's describe.
5659
+ *
5660
+ * **Mode interaction:**
5661
+ * - In `mode: "enforce"` (default), the enforcer stacks a policy-derived
5662
+ * guard on every target node. `scopedDescribe({actor})` then filters by
5663
+ * the AND of per-node guards AND the stacked policy guard.
5664
+ * - In `mode: "audit"`, NO guards are stacked — `scopedDescribe` filters
5665
+ * purely by the target's pre-existing per-node guards. If a target has
5666
+ * no node-level guards, the policy rules you pass have no effect on
5667
+ * visibility (they only populate the `violations` topic on writes).
5668
+ */
5669
+ scopedDescribe(opts) {
5670
+ const actor = opts?.actor ?? this._defaultActor;
5671
+ const describeOpts = {
5672
+ ...opts,
5673
+ ...actor != null ? { actor } : {}
5674
+ };
5675
+ return this._target.describe(describeOpts);
5676
+ }
5677
+ /** The wrapped graph (escape hatch for tooling). */
5678
+ get target() {
5679
+ return this._target;
5680
+ }
5681
+ };
5682
+ function guardedExecution(target, opts) {
5683
+ return new GuardedExecutionGraph(target, opts);
5684
+ }
5685
+
6304
5686
  // src/patterns/harness/index.ts
6305
5687
  var harness_exports = {};
6306
5688
  __export(harness_exports, {
@@ -6379,8 +5761,8 @@ function evalIntakeBridge(evalSource2, intakeTopic, opts) {
6379
5761
  { name: opts?.name ?? "eval-intake-bridge" }
6380
5762
  );
6381
5763
  }
6382
- function evalSource(trigger2, runner) {
6383
- return switchMap(trigger2, () => fromAny(runner()));
5764
+ function evalSource(trigger, runner) {
5765
+ return switchMap(trigger, () => fromAny(runner()));
6384
5766
  }
6385
5767
  function beforeAfterCompare(before, after) {
6386
5768
  return derived(
@@ -6982,6 +6364,636 @@ function truncate(s, max) {
6982
6364
  return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
6983
6365
  }
6984
6366
 
6367
+ // src/patterns/lens.ts
6368
+ var lens_exports = {};
6369
+ __export(lens_exports, {
6370
+ LensGraph: () => LensGraph,
6371
+ graphLens: () => graphLens,
6372
+ watchTopologyTree: () => watchTopologyTree
6373
+ });
6374
+ function lensMeta(kind) {
6375
+ return domainMeta("lens", kind);
6376
+ }
6377
+ function computeTopologyStats(described) {
6378
+ const paths = Object.keys(described.nodes);
6379
+ const depsByPath = /* @__PURE__ */ new Map();
6380
+ const dependents = /* @__PURE__ */ new Map();
6381
+ for (const path of paths) {
6382
+ const deps = described.nodes[path]?.deps ?? [];
6383
+ depsByPath.set(path, deps);
6384
+ for (const dep of deps) {
6385
+ if (!dependents.has(dep)) dependents.set(dep, /* @__PURE__ */ new Set());
6386
+ dependents.get(dep).add(path);
6387
+ }
6388
+ }
6389
+ const sources = [];
6390
+ const sinks = [];
6391
+ for (const path of paths) {
6392
+ if ((depsByPath.get(path) ?? []).length === 0) sources.push(path);
6393
+ if (!dependents.has(path)) sinks.push(path);
6394
+ }
6395
+ sources.sort();
6396
+ sinks.sort();
6397
+ const edgeCount = described.edges.length;
6398
+ const WHITE = 0;
6399
+ const GRAY = 1;
6400
+ const BLACK = 2;
6401
+ const color = /* @__PURE__ */ new Map();
6402
+ for (const p of paths) color.set(p, WHITE);
6403
+ let hasCycles = false;
6404
+ const longestFrom = /* @__PURE__ */ new Map();
6405
+ const dfs = (path) => {
6406
+ const c = color.get(path) ?? WHITE;
6407
+ if (c === GRAY) {
6408
+ hasCycles = true;
6409
+ return 0;
6410
+ }
6411
+ if (c === BLACK) return longestFrom.get(path) ?? 0;
6412
+ color.set(path, GRAY);
6413
+ let best = 0;
6414
+ const kids = dependents.get(path);
6415
+ if (kids != null) {
6416
+ for (const k of kids) {
6417
+ const childLongest = dfs(k);
6418
+ if (childLongest + 1 > best) best = childLongest + 1;
6419
+ }
6420
+ }
6421
+ color.set(path, BLACK);
6422
+ longestFrom.set(path, best);
6423
+ return best;
6424
+ };
6425
+ let depth = 0;
6426
+ for (const src of sources) {
6427
+ const d = dfs(src);
6428
+ if (d > depth) depth = d;
6429
+ }
6430
+ for (const p of paths) {
6431
+ if (color.get(p) === WHITE) dfs(p);
6432
+ }
6433
+ return {
6434
+ nodeCount: paths.length,
6435
+ edgeCount,
6436
+ subgraphCount: described.subgraphs.length,
6437
+ sources,
6438
+ sinks,
6439
+ depth,
6440
+ hasCycles
6441
+ };
6442
+ }
6443
+ function computeHealthReport(described) {
6444
+ const problems = [];
6445
+ for (const [path, desc] of Object.entries(described.nodes)) {
6446
+ if (desc.status !== "errored") continue;
6447
+ const entry = { path, status: "errored" };
6448
+ const upstream = reachable(described, path, "upstream", {});
6449
+ for (const p of upstream) {
6450
+ if (p === path) continue;
6451
+ if (described.nodes[p]?.status === "errored") {
6452
+ entry.upstreamCause = p;
6453
+ break;
6454
+ }
6455
+ }
6456
+ problems.push(entry);
6457
+ }
6458
+ problems.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
6459
+ return { ok: problems.length === 0, problems };
6460
+ }
6461
+ function topologyStatsEqual(a, b) {
6462
+ return a.nodeCount === b.nodeCount && a.edgeCount === b.edgeCount && a.subgraphCount === b.subgraphCount && a.depth === b.depth && a.hasCycles === b.hasCycles && stringArrayEqual(a.sources, b.sources) && stringArrayEqual(a.sinks, b.sinks);
6463
+ }
6464
+ function healthReportEqual(a, b) {
6465
+ if (a.ok !== b.ok) return false;
6466
+ if (a.problems.length !== b.problems.length) return false;
6467
+ for (let i = 0; i < a.problems.length; i++) {
6468
+ const x = a.problems[i];
6469
+ const y = b.problems[i];
6470
+ if (x.path !== y.path) return false;
6471
+ if (x.status !== y.status) return false;
6472
+ if (x.upstreamCause !== y.upstreamCause) return false;
6473
+ }
6474
+ return true;
6475
+ }
6476
+ function stringArrayEqual(a, b) {
6477
+ if (a.length !== b.length) return false;
6478
+ for (let i = 0; i < a.length; i++) {
6479
+ if (a[i] !== b[i]) return false;
6480
+ }
6481
+ return true;
6482
+ }
6483
+ var LensGraph = class extends Graph {
6484
+ /**
6485
+ * Aggregate structural stats — `nodeCount`, `edgeCount`, `sources`,
6486
+ * `sinks`, `depth`, `hasCycles`, `subgraphCount`. Recomputes on every
6487
+ * structural change via {@link watchTopologyTree} (transitive).
6488
+ *
6489
+ * Named `stats` (not `topology`) because `Graph.topology` already names
6490
+ * the raw `TopologyEvent` stream on every graph including `LensGraph`;
6491
+ * giving the lens its own `topology` accessor with an incompatible
6492
+ * `Node<TopologyStats>` type would break Liskov substitutability.
6493
+ */
6494
+ stats;
6495
+ health;
6496
+ /**
6497
+ * Per-path flow tracker — a live {@link ReactiveMapBundle} keyed by
6498
+ * qualified path. Use `.get(path)` / `.has(path)` / `.size` for O(1)
6499
+ * sync queries; subscribe to `.entries` for a reactive snapshot of the
6500
+ * whole map. Lazy — the snapshot is materialized only while `.entries`
6501
+ * has subscribers.
6502
+ *
6503
+ * Shape intentionally differs from `stats` / `health` (which are plain
6504
+ * `Node<Report>`) because `flow` is a keyed collection, not a single
6505
+ * aggregate value. The map shape exposes cheaper queries than any
6506
+ * snapshot-based design.
6507
+ */
6508
+ flow;
6509
+ _target;
6510
+ constructor(target, opts = {}) {
6511
+ super(opts.name ?? `${target.name}_lens`, opts.graph);
6512
+ this._target = target;
6513
+ let statsVersion = 0;
6514
+ let healthVersion = 0;
6515
+ const statsTick = state(0, { name: "stats_tick" });
6516
+ const healthTick = state(0, { name: "health_tick" });
6517
+ this.add("stats_tick", statsTick);
6518
+ this.add("health_tick", healthTick);
6519
+ const mapOpts = { name: "flow" };
6520
+ if (opts.maxFlowPaths != null) mapOpts.maxSize = opts.maxFlowPaths;
6521
+ this.flow = reactiveMap(mapOpts);
6522
+ this.add("flow", this.flow.entries);
6523
+ const pathFilter = opts.pathFilter;
6524
+ const offTopology = watchTopologyTree(target, (event, _emitter, prefix) => {
6525
+ statsVersion += 1;
6526
+ statsTick.emit(statsVersion);
6527
+ healthVersion += 1;
6528
+ healthTick.emit(healthVersion);
6529
+ if (event.kind === "removed") {
6530
+ if (event.nodeKind === "node") {
6531
+ const qp = `${prefix}${event.name}`;
6532
+ this.flow.delete(qp);
6533
+ } else {
6534
+ const mountPrefix = `${prefix}${event.name}::`;
6535
+ const keysToDelete = [];
6536
+ for (const relativePath of event.audit.nodes) {
6537
+ const qualified = relativePath === "" ? `${prefix}${event.name}` : `${mountPrefix}${relativePath}`;
6538
+ keysToDelete.push(qualified);
6539
+ }
6540
+ if (keysToDelete.length > 0) this.flow.deleteMany(keysToDelete);
6541
+ }
6542
+ }
6543
+ });
6544
+ this.addDisposer(offTopology);
6545
+ const observeHandle = target.observe({ timeline: true, structured: true });
6546
+ const offObserve = observeHandle.onEvent((event) => {
6547
+ const t = event.type;
6548
+ if (t === "error" || t === "complete" || t === "data" || t === "teardown") {
6549
+ healthVersion += 1;
6550
+ healthTick.emit(healthVersion);
6551
+ }
6552
+ if (t === "data") {
6553
+ const path = event.path ?? "";
6554
+ if (!path) return;
6555
+ if (pathFilter != null && !pathFilter(path)) return;
6556
+ const existing = this.flow.get(path);
6557
+ const count = existing != null ? existing.count + 1 : 1;
6558
+ this.flow.set(path, { path, count, lastUpdate_ns: monotonicNs() });
6559
+ }
6560
+ });
6561
+ this.addDisposer(() => {
6562
+ offObserve();
6563
+ observeHandle.dispose();
6564
+ });
6565
+ this.stats = derived(
6566
+ [statsTick],
6567
+ () => computeTopologyStats(target.describe({ detail: "minimal" })),
6568
+ {
6569
+ name: "stats",
6570
+ describeKind: "derived",
6571
+ equals: topologyStatsEqual,
6572
+ meta: lensMeta("stats")
6573
+ }
6574
+ );
6575
+ this.add("stats", this.stats);
6576
+ this.addDisposer(keepalive(this.stats));
6577
+ this.health = derived(
6578
+ [healthTick],
6579
+ () => computeHealthReport(target.describe({ detail: "standard" })),
6580
+ {
6581
+ name: "health",
6582
+ describeKind: "derived",
6583
+ equals: healthReportEqual,
6584
+ meta: lensMeta("health")
6585
+ }
6586
+ );
6587
+ this.add("health", this.health);
6588
+ this.addDisposer(keepalive(this.health));
6589
+ }
6590
+ /**
6591
+ * Live causal chain from `from` to `to`. Recomputes whenever the target
6592
+ * mutates. Disposed automatically when the lens is destroyed.
6593
+ *
6594
+ * **Lifetime note:** every call to `why()` registers a lens-owned disposer
6595
+ * that runs on `lens.destroy()`. The returned `dispose` function releases
6596
+ * the internal subscription but does NOT remove the lens-owned disposer —
6597
+ * so heavy calling (e.g. per render frame) accumulates no-op disposers
6598
+ * until lens teardown. Cache the returned handle for long-lived queries.
6599
+ *
6600
+ * @param from - Qualified path of the upstream endpoint.
6601
+ * @param to - Qualified path of the downstream endpoint.
6602
+ * @param opts - See {@link reactiveExplainPath}.
6603
+ */
6604
+ why(from, to, opts) {
6605
+ const handle = reactiveExplainPath(this._target, from, to, opts);
6606
+ this.addDisposer(handle.dispose);
6607
+ return handle;
6608
+ }
6609
+ /** Reference to the lensed graph. */
6610
+ get target() {
6611
+ return this._target;
6612
+ }
6613
+ };
6614
+ function graphLens(target, opts) {
6615
+ return new LensGraph(target, opts);
6616
+ }
6617
+
6618
+ // src/patterns/resilient-pipeline.ts
6619
+ var resilient_pipeline_exports = {};
6620
+ __export(resilient_pipeline_exports, {
6621
+ NS_PER_MS: () => NS_PER_MS,
6622
+ NS_PER_SEC: () => NS_PER_SEC,
6623
+ resilientPipeline: () => resilientPipeline
6624
+ });
6625
+ function resilientPipeline(source, opts = {}) {
6626
+ let current = source;
6627
+ if (opts.rateLimit != null) {
6628
+ current = rateLimiter(current, opts.rateLimit);
6629
+ }
6630
+ if (opts.budget != null && opts.budget.length > 0) {
6631
+ current = budgetGate(current, opts.budget);
6632
+ }
6633
+ let breakerState;
6634
+ if (opts.breaker != null) {
6635
+ const breaker = circuitBreaker(opts.breaker);
6636
+ const onOpen = opts.breakerOnOpen ?? "skip";
6637
+ const wrapped = withBreaker(breaker, { onOpen })(current);
6638
+ current = wrapped.node;
6639
+ breakerState = wrapped.breakerState;
6640
+ }
6641
+ if (opts.timeoutMs != null) {
6642
+ if (opts.timeoutMs <= 0) throw new RangeError("timeoutMs must be > 0");
6643
+ if (opts.timeoutMs > 9e6) {
6644
+ throw new RangeError(
6645
+ "timeoutMs must be <= 9_000_000 (\u22482.5h) to stay within safe ns arithmetic"
6646
+ );
6647
+ }
6648
+ current = timeout(current, opts.timeoutMs * NS_PER_MS);
6649
+ }
6650
+ if (opts.retry != null) {
6651
+ current = retry(current, opts.retry);
6652
+ }
6653
+ if (opts.fallback !== void 0) {
6654
+ current = fallback(current, opts.fallback);
6655
+ }
6656
+ const withStatusBundle = withStatus(current, { initialStatus: opts.initialStatus ?? "pending" });
6657
+ return {
6658
+ node: withStatusBundle.node,
6659
+ status: withStatusBundle.status,
6660
+ error: withStatusBundle.error,
6661
+ breakerState
6662
+ };
6663
+ }
6664
+
6665
+ // src/patterns/surface/index.ts
6666
+ var surface_exports = {};
6667
+ __export(surface_exports, {
6668
+ SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
6669
+ SurfaceError: () => SurfaceError,
6670
+ asSurfaceError: () => asSurfaceError,
6671
+ createGraph: () => createGraph,
6672
+ deleteSnapshot: () => deleteSnapshot,
6673
+ diffSnapshots: () => diffSnapshots,
6674
+ listSnapshots: () => listSnapshots,
6675
+ restoreSnapshot: () => restoreSnapshot,
6676
+ runReduction: () => runReduction,
6677
+ saveSnapshot: () => saveSnapshot
6678
+ });
6679
+
6680
+ // src/patterns/surface/errors.ts
6681
+ var SurfaceError = class extends Error {
6682
+ code;
6683
+ details;
6684
+ constructor(code, message, details) {
6685
+ super(message);
6686
+ this.name = "SurfaceError";
6687
+ this.code = code;
6688
+ if (details !== void 0) this.details = details;
6689
+ }
6690
+ /**
6691
+ * JSON-safe payload for wire serialization. Defensively validates
6692
+ * `details` — if it can't be round-tripped through `JSON.stringify`
6693
+ * (cyclic refs, `BigInt`, `Error` instance not pre-toJSON'd), the
6694
+ * payload falls back to `{code, message}` only rather than crashing
6695
+ * the MCP/CLI wrapper when it serializes this error onto the wire.
6696
+ */
6697
+ toJSON() {
6698
+ const out = { code: this.code, message: this.message };
6699
+ if (this.details !== void 0) {
6700
+ const safe = safeDetails(this.details);
6701
+ if (safe !== void 0) out.details = safe;
6702
+ }
6703
+ return out;
6704
+ }
6705
+ };
6706
+ function safeDetails(details) {
6707
+ try {
6708
+ return JSON.parse(JSON.stringify(details));
6709
+ } catch {
6710
+ return void 0;
6711
+ }
6712
+ }
6713
+ function asSurfaceError(err, fallbackCode = "internal-error") {
6714
+ if (err instanceof SurfaceError) return err;
6715
+ const message = err instanceof Error ? err.message : String(err);
6716
+ return new SurfaceError(fallbackCode, message);
6717
+ }
6718
+
6719
+ // src/patterns/surface/create.ts
6720
+ function createGraph(spec, opts) {
6721
+ const structural = validateSpec(spec);
6722
+ if (!structural.valid) {
6723
+ throw new SurfaceError(
6724
+ "invalid-spec",
6725
+ `GraphSpec validation failed:
6726
+ ${structural.errors.join("\n")}`,
6727
+ { errors: structural.errors }
6728
+ );
6729
+ }
6730
+ const catalog = opts?.catalog ?? {};
6731
+ const catalogValidation = validateSpecAgainstCatalog(spec, catalog);
6732
+ if (!catalogValidation.valid) {
6733
+ throw new SurfaceError(
6734
+ "catalog-error",
6735
+ `Catalog validation failed:
6736
+ ${catalogValidation.errors.join("\n")}`,
6737
+ { errors: catalogValidation.errors }
6738
+ );
6739
+ }
6740
+ try {
6741
+ return compileSpec(spec, opts);
6742
+ } catch (err) {
6743
+ const message = err instanceof Error ? err.message : String(err);
6744
+ throw new SurfaceError("catalog-error", message);
6745
+ }
6746
+ }
6747
+
6748
+ // src/patterns/surface/reduce.ts
6749
+ var DEFAULT_TIMEOUT_MS2 = 3e4;
6750
+ async function runReduction(spec, input, opts) {
6751
+ const inputPath = opts?.inputPath ?? "input";
6752
+ const outputPath = opts?.outputPath ?? "output";
6753
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
6754
+ const graph = createGraph(spec, { catalog: opts?.catalog });
6755
+ let outputNode;
6756
+ try {
6757
+ outputNode = graph.resolve(outputPath);
6758
+ } catch {
6759
+ graph.destroy();
6760
+ throw new SurfaceError(
6761
+ "node-not-found",
6762
+ `reduce: output path "${outputPath}" is not registered`,
6763
+ { path: outputPath }
6764
+ );
6765
+ }
6766
+ try {
6767
+ graph.resolve(inputPath);
6768
+ } catch {
6769
+ graph.destroy();
6770
+ throw new SurfaceError(
6771
+ "node-not-found",
6772
+ `reduce: input path "${inputPath}" is not registered`,
6773
+ { path: inputPath }
6774
+ );
6775
+ }
6776
+ try {
6777
+ return await new Promise((resolve, reject) => {
6778
+ let primed = false;
6779
+ let settled = false;
6780
+ let timer;
6781
+ let unsub;
6782
+ let shouldUnsub = false;
6783
+ const finish = (action) => {
6784
+ if (settled) return;
6785
+ settled = true;
6786
+ if (timer !== void 0) clearTimeout(timer);
6787
+ if (unsub !== void 0) {
6788
+ unsub();
6789
+ unsub = void 0;
6790
+ } else {
6791
+ shouldUnsub = true;
6792
+ }
6793
+ action();
6794
+ };
6795
+ unsub = outputNode.subscribe((msgs) => {
6796
+ for (const m of msgs) {
6797
+ if (settled) return;
6798
+ if (!primed) continue;
6799
+ if (m[0] === DATA) {
6800
+ finish(() => resolve(m[1]));
6801
+ return;
6802
+ }
6803
+ if (m[0] === RESOLVED) {
6804
+ const cached2 = outputNode.cache;
6805
+ finish(() => resolve(cached2));
6806
+ return;
6807
+ }
6808
+ if (m[0] === ERROR) {
6809
+ const payload = m[1];
6810
+ const message = payload instanceof Error ? payload.message : String(payload);
6811
+ const cause = payload instanceof Error ? payload : void 0;
6812
+ finish(
6813
+ () => reject(
6814
+ new SurfaceError(
6815
+ "internal-error",
6816
+ `reduce: output emitted ERROR: ${message}`,
6817
+ cause != null ? { cause } : void 0
6818
+ )
6819
+ )
6820
+ );
6821
+ return;
6822
+ }
6823
+ if (m[0] === COMPLETE) {
6824
+ finish(
6825
+ () => reject(
6826
+ new SurfaceError(
6827
+ "internal-error",
6828
+ `reduce: output COMPLETEd without a post-push DATA`
6829
+ )
6830
+ )
6831
+ );
6832
+ return;
6833
+ }
6834
+ }
6835
+ });
6836
+ if (shouldUnsub) {
6837
+ unsub?.();
6838
+ unsub = void 0;
6839
+ }
6840
+ primed = true;
6841
+ try {
6842
+ graph.set(inputPath, input);
6843
+ } catch (err) {
6844
+ const message = err instanceof Error ? err.message : String(err);
6845
+ const cause = err instanceof Error ? err : void 0;
6846
+ finish(
6847
+ () => reject(
6848
+ new SurfaceError(
6849
+ "internal-error",
6850
+ `reduce: failed to set input on "${inputPath}": ${message}`,
6851
+ cause != null ? { path: inputPath, cause } : { path: inputPath }
6852
+ )
6853
+ )
6854
+ );
6855
+ return;
6856
+ }
6857
+ if (!settled && Number.isFinite(timeoutMs) && timeoutMs > 0) {
6858
+ timer = setTimeout(() => {
6859
+ finish(
6860
+ () => reject(
6861
+ new SurfaceError(
6862
+ "reduce-timeout",
6863
+ `reduce: no output emitted within ${timeoutMs}ms`,
6864
+ { timeoutMs, outputPath }
6865
+ )
6866
+ )
6867
+ );
6868
+ }, timeoutMs);
6869
+ timer.unref?.();
6870
+ }
6871
+ });
6872
+ } finally {
6873
+ graph.destroy();
6874
+ }
6875
+ }
6876
+
6877
+ // src/patterns/surface/snapshot.ts
6878
+ var SNAPSHOT_WIRE_VERSION = SNAPSHOT_VERSION;
6879
+ function unwrapCheckpoint(raw, snapshotId) {
6880
+ if (raw == null || typeof raw !== "object") {
6881
+ throw new SurfaceError("snapshot-not-found", `snapshot "${snapshotId}" not found in tier`, {
6882
+ snapshotId
6883
+ });
6884
+ }
6885
+ const record = raw;
6886
+ if ("mode" in record) {
6887
+ if (record.mode === "full" && "snapshot" in record) {
6888
+ return record.snapshot;
6889
+ }
6890
+ if (record.mode === "diff") {
6891
+ throw new SurfaceError(
6892
+ "restore-failed",
6893
+ `snapshot "${snapshotId}" is a diff record; restore the baseline and replay WAL instead`,
6894
+ { snapshotId, mode: "diff" }
6895
+ );
6896
+ }
6897
+ throw new SurfaceError(
6898
+ "restore-failed",
6899
+ `snapshot "${snapshotId}" has unknown mode "${String(record.mode)}"`,
6900
+ { snapshotId, mode: String(record.mode) }
6901
+ );
6902
+ }
6903
+ if ("nodes" in record && "edges" in record && "subgraphs" in record && "name" in record) {
6904
+ return record;
6905
+ }
6906
+ throw new SurfaceError(
6907
+ "restore-failed",
6908
+ `snapshot "${snapshotId}" payload is not a GraphCheckpointRecord or GraphPersistSnapshot`,
6909
+ { snapshotId }
6910
+ );
6911
+ }
6912
+ async function saveSnapshot(graph, snapshotId, tier) {
6913
+ let snapshot;
6914
+ try {
6915
+ snapshot = graph.snapshot();
6916
+ } catch (err) {
6917
+ const message = err instanceof Error ? err.message : String(err);
6918
+ throw new SurfaceError(
6919
+ "snapshot-failed",
6920
+ `snapshot "${snapshotId}" serialization failed: ${message}`,
6921
+ { snapshotId }
6922
+ );
6923
+ }
6924
+ const record = {
6925
+ mode: "full",
6926
+ seq: 0,
6927
+ timestamp_ns: wallClockNs(),
6928
+ format_version: SNAPSHOT_WIRE_VERSION,
6929
+ snapshot
6930
+ };
6931
+ try {
6932
+ await tier.save(snapshotId, record);
6933
+ } catch (err) {
6934
+ const message = err instanceof Error ? err.message : String(err);
6935
+ throw new SurfaceError("snapshot-failed", `snapshot "${snapshotId}" save failed: ${message}`, {
6936
+ snapshotId
6937
+ });
6938
+ }
6939
+ return { snapshotId, timestamp_ns: record.timestamp_ns };
6940
+ }
6941
+ async function restoreSnapshot(snapshotId, tier, opts) {
6942
+ const raw = await tier.load(snapshotId);
6943
+ const snapshot = unwrapCheckpoint(raw, snapshotId);
6944
+ try {
6945
+ return Graph.fromSnapshot(
6946
+ snapshot,
6947
+ opts?.factories ? { factories: opts.factories } : void 0
6948
+ );
6949
+ } catch (err) {
6950
+ const message = err instanceof Error ? err.message : String(err);
6951
+ throw new SurfaceError(
6952
+ "restore-failed",
6953
+ `snapshot "${snapshotId}" restore failed: ${message}`,
6954
+ {
6955
+ snapshotId
6956
+ }
6957
+ );
6958
+ }
6959
+ }
6960
+ async function diffSnapshots(snapshotIdA, snapshotIdB, tier) {
6961
+ const [rawA, rawB] = await Promise.all([tier.load(snapshotIdA), tier.load(snapshotIdB)]);
6962
+ const snapshotA = unwrapCheckpoint(rawA, snapshotIdA);
6963
+ const snapshotB = unwrapCheckpoint(rawB, snapshotIdB);
6964
+ return Graph.diff(snapshotA, snapshotB);
6965
+ }
6966
+ async function listSnapshots(tier) {
6967
+ if (typeof tier.list !== "function") {
6968
+ throw new SurfaceError(
6969
+ "tier-no-list",
6970
+ "StorageTier does not implement list(); wrap the tier with an enumerator or use a different backend"
6971
+ );
6972
+ }
6973
+ return tier.list();
6974
+ }
6975
+ async function deleteSnapshot(snapshotId, tier) {
6976
+ if (typeof tier.clear !== "function") {
6977
+ throw new SurfaceError(
6978
+ "snapshot-failed",
6979
+ `StorageTier is append-only (no clear()); cannot delete "${snapshotId}"`,
6980
+ { snapshotId }
6981
+ );
6982
+ }
6983
+ try {
6984
+ await tier.clear(snapshotId);
6985
+ } catch (err) {
6986
+ const message = err instanceof Error ? err.message : String(err);
6987
+ throw new SurfaceError(
6988
+ "snapshot-failed",
6989
+ `snapshot "${snapshotId}" delete failed: ${message}`,
6990
+ {
6991
+ snapshotId
6992
+ }
6993
+ );
6994
+ }
6995
+ }
6996
+
6985
6997
  // src/index.ts
6986
6998
  var version = "0.0.0";
6987
6999
  export {
@@ -7021,15 +7033,20 @@ export {
7021
7033
  ResettableTimer,
7022
7034
  OVERHEAD as SIZEOF_OVERHEAD,
7023
7035
  SIZEOF_SYMBOL,
7036
+ SNAPSHOT_VERSION,
7037
+ SNAPSHOT_WIRE_VERSION,
7024
7038
  START,
7025
7039
  START_MSG,
7040
+ SurfaceError,
7026
7041
  TEARDOWN,
7027
7042
  TEARDOWN_MSG,
7028
7043
  TEARDOWN_ONLY_BATCH,
7029
7044
  TimeoutError,
7030
7045
  accessHintForGuard,
7046
+ audit_exports as accountability,
7031
7047
  advanceVersion,
7032
7048
  ai_exports as ai,
7049
+ asSurfaceError,
7033
7050
  audit,
7034
7051
  autoTrackNode,
7035
7052
  batch,
@@ -7053,6 +7070,7 @@ export {
7053
7070
  cqrs_exports as cqrs,
7054
7071
  createDagCborCodec,
7055
7072
  createDagCborZstdCodec,
7073
+ createGraph,
7056
7074
  createTransport,
7057
7075
  createVersioning,
7058
7076
  createWatermarkController,
@@ -7064,11 +7082,13 @@ export {
7064
7082
  defaultConfig,
7065
7083
  defaultHash,
7066
7084
  delay,
7085
+ deleteSnapshot,
7067
7086
  demo_shell_exports as demoShell,
7068
7087
  derived,
7069
7088
  deserializeError,
7070
7089
  dictStorage,
7071
7090
  diffForWAL,
7091
+ diffSnapshots,
7072
7092
  distill,
7073
7093
  distinctUntilChanged,
7074
7094
  domain_templates_exports as domainTemplates,
@@ -7080,6 +7100,7 @@ export {
7080
7100
  encodeEnvelope,
7081
7101
  escapeRegexChar,
7082
7102
  exhaustMap,
7103
+ explainPath,
7083
7104
  exponential,
7084
7105
  externalBundle,
7085
7106
  externalProducer,
@@ -7135,6 +7156,7 @@ export {
7135
7156
  graph_exports as graph,
7136
7157
  graphProfile,
7137
7158
  graphspec_exports as graphspec,
7159
+ guarded_execution_exports as guarded,
7138
7160
  harness_exports as harness,
7139
7161
  indexedDbStorage,
7140
7162
  interval,
@@ -7144,7 +7166,9 @@ export {
7144
7166
  keepalive,
7145
7167
  last,
7146
7168
  reactive_layout_exports as layout,
7169
+ lens_exports as lens,
7147
7170
  linear,
7171
+ listSnapshots,
7148
7172
  lru,
7149
7173
  map,
7150
7174
  matchesAnyPattern,
@@ -7194,11 +7218,15 @@ export {
7194
7218
  replay,
7195
7219
  replayWAL,
7196
7220
  rescue,
7221
+ resilient_pipeline_exports as resilientPipeline,
7197
7222
  resolveBackoffPreset,
7198
7223
  resolveDescribeFields,
7224
+ restoreSnapshot,
7199
7225
  retry,
7200
7226
  retrySource,
7227
+ runReduction,
7201
7228
  sample,
7229
+ saveSnapshot,
7202
7230
  scan,
7203
7231
  serializeError,
7204
7232
  share,
@@ -7210,6 +7238,7 @@ export {
7210
7238
  solid_exports as solid,
7211
7239
  sqliteStorage,
7212
7240
  state,
7241
+ surface_exports as surface,
7213
7242
  svelte_exports as svelte,
7214
7243
  switchMap,
7215
7244
  take,
@@ -7247,6 +7276,7 @@ export {
7247
7276
  version,
7248
7277
  vue_exports as vue,
7249
7278
  wallClockNs,
7279
+ watchTopologyTree,
7250
7280
  window,
7251
7281
  windowCount,
7252
7282
  windowTime,