@graphrefly/graphrefly 0.24.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-5WGT55R4.js → chunk-AMCG74RZ.js} +195 -24
  7. package/dist/chunk-AMCG74RZ.js.map +1 -0
  8. package/dist/{chunk-AOCBDH4T.js → chunk-BVZYTZ5H.js} +76 -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-IPLKX3L2.js → chunk-IZYUSJC7.js} +16 -14
  15. package/dist/{chunk-IPLKX3L2.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-LCE3GF5P.js +866 -0
  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-TDEXAMGO.js → chunk-ZQMEI34O.js} +206 -574
  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 +290 -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 +8 -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-D-3JIQme.d.cts → graph-6tZ5jEzr.d.cts} +195 -4
  122. package/dist/{graph-B6NFqv3z.d.ts → 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-D7XgsUt7.d.ts → index-BW1z3BN9.d.ts} +169 -127
  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-BysCTzJz.d.ts → index-BeIdBfcb.d.cts} +121 -547
  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-b5BYtczN.d.cts → index-C8mdwMXc.d.cts} +169 -127
  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-1z8vRTCt.d.cts → index-DdD5MVDL.d.ts} +121 -547
  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 +2334 -195
  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 +1204 -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 +843 -29
  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 +25 -10
  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-5WGT55R4.js.map +0 -1
  179. package/dist/chunk-AOCBDH4T.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-TDEXAMGO.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.cjs CHANGED
@@ -101,15 +101,20 @@ __export(index_exports, {
101
101
  ResettableTimer: () => ResettableTimer,
102
102
  SIZEOF_OVERHEAD: () => OVERHEAD,
103
103
  SIZEOF_SYMBOL: () => SIZEOF_SYMBOL,
104
+ SNAPSHOT_VERSION: () => SNAPSHOT_VERSION,
105
+ SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
104
106
  START: () => START,
105
107
  START_MSG: () => START_MSG,
108
+ SurfaceError: () => SurfaceError,
106
109
  TEARDOWN: () => TEARDOWN,
107
110
  TEARDOWN_MSG: () => TEARDOWN_MSG,
108
111
  TEARDOWN_ONLY_BATCH: () => TEARDOWN_ONLY_BATCH,
109
112
  TimeoutError: () => TimeoutError,
110
113
  accessHintForGuard: () => accessHintForGuard,
114
+ accountability: () => audit_exports,
111
115
  advanceVersion: () => advanceVersion,
112
116
  ai: () => ai_exports,
117
+ asSurfaceError: () => asSurfaceError,
113
118
  audit: () => audit,
114
119
  autoTrackNode: () => autoTrackNode,
115
120
  batch: () => batch,
@@ -133,6 +138,7 @@ __export(index_exports, {
133
138
  cqrs: () => cqrs_exports,
134
139
  createDagCborCodec: () => createDagCborCodec,
135
140
  createDagCborZstdCodec: () => createDagCborZstdCodec,
141
+ createGraph: () => createGraph,
136
142
  createTransport: () => createTransport,
137
143
  createVersioning: () => createVersioning,
138
144
  createWatermarkController: () => createWatermarkController,
@@ -144,11 +150,13 @@ __export(index_exports, {
144
150
  defaultConfig: () => defaultConfig,
145
151
  defaultHash: () => defaultHash,
146
152
  delay: () => delay,
153
+ deleteSnapshot: () => deleteSnapshot,
147
154
  demoShell: () => demo_shell_exports,
148
155
  derived: () => derived,
149
156
  deserializeError: () => deserializeError,
150
157
  dictStorage: () => dictStorage,
151
158
  diffForWAL: () => diffForWAL,
159
+ diffSnapshots: () => diffSnapshots,
152
160
  distill: () => distill,
153
161
  distinctUntilChanged: () => distinctUntilChanged,
154
162
  domainTemplates: () => domain_templates_exports,
@@ -160,6 +168,7 @@ __export(index_exports, {
160
168
  encodeEnvelope: () => encodeEnvelope,
161
169
  escapeRegexChar: () => escapeRegexChar,
162
170
  exhaustMap: () => exhaustMap,
171
+ explainPath: () => explainPath,
163
172
  exponential: () => exponential,
164
173
  externalBundle: () => externalBundle,
165
174
  externalProducer: () => externalProducer,
@@ -200,6 +209,7 @@ __export(index_exports, {
200
209
  fromPromise: () => fromPromise,
201
210
  fromPulsar: () => fromPulsar,
202
211
  fromRabbitMQ: () => fromRabbitMQ,
212
+ fromRaf: () => fromRaf,
203
213
  fromRedisStream: () => fromRedisStream,
204
214
  fromSSE: () => fromSSE,
205
215
  fromSqlite: () => fromSqlite,
@@ -214,6 +224,7 @@ __export(index_exports, {
214
224
  graph: () => graph_exports,
215
225
  graphProfile: () => graphProfile,
216
226
  graphspec: () => graphspec_exports,
227
+ guarded: () => guarded_execution_exports,
217
228
  harness: () => harness_exports,
218
229
  indexedDbStorage: () => indexedDbStorage,
219
230
  interval: () => interval,
@@ -223,7 +234,9 @@ __export(index_exports, {
223
234
  keepalive: () => keepalive,
224
235
  last: () => last,
225
236
  layout: () => reactive_layout_exports,
237
+ lens: () => lens_exports,
226
238
  linear: () => linear,
239
+ listSnapshots: () => listSnapshots,
227
240
  lru: () => lru,
228
241
  map: () => map2,
229
242
  matchesAnyPattern: () => matchesAnyPattern,
@@ -273,11 +286,15 @@ __export(index_exports, {
273
286
  replay: () => replay,
274
287
  replayWAL: () => replayWAL,
275
288
  rescue: () => rescue,
289
+ resilientPipeline: () => resilient_pipeline_exports,
276
290
  resolveBackoffPreset: () => resolveBackoffPreset,
277
291
  resolveDescribeFields: () => resolveDescribeFields,
292
+ restoreSnapshot: () => restoreSnapshot,
278
293
  retry: () => retry,
279
294
  retrySource: () => retrySource,
295
+ runReduction: () => runReduction,
280
296
  sample: () => sample,
297
+ saveSnapshot: () => saveSnapshot,
281
298
  scan: () => scan,
282
299
  serializeError: () => serializeError,
283
300
  share: () => share,
@@ -289,6 +306,7 @@ __export(index_exports, {
289
306
  solid: () => solid_exports,
290
307
  sqliteStorage: () => sqliteStorage,
291
308
  state: () => state,
309
+ surface: () => surface_exports,
292
310
  svelte: () => svelte_exports,
293
311
  switchMap: () => switchMap,
294
312
  take: () => take,
@@ -326,6 +344,7 @@ __export(index_exports, {
326
344
  version: () => version,
327
345
  vue: () => vue_exports,
328
346
  wallClockNs: () => wallClockNs,
347
+ watchTopologyTree: () => watchTopologyTree,
329
348
  window: () => window,
330
349
  windowCount: () => windowCount,
331
350
  windowTime: () => windowTime,
@@ -1337,6 +1356,12 @@ var NodeImpl = class _NodeImpl {
1337
1356
  _autoError;
1338
1357
  _pausable;
1339
1358
  _guard;
1359
+ /**
1360
+ * @internal Additional guards stacked at runtime via {@link NodeImpl._pushGuard}
1361
+ * (e.g. by `policyEnforcer({ mode: "enforce" })`, roadmap §9.2). Effective
1362
+ * write/signal/observe checks AND the original `_guard` with every entry here.
1363
+ */
1364
+ _extraGuards;
1340
1365
  _hashFn;
1341
1366
  _versioning;
1342
1367
  /**
@@ -1510,18 +1535,61 @@ var NodeImpl = class _NodeImpl {
1510
1535
  if (this._inspectorHooks?.size === 0) this._inspectorHooks = void 0;
1511
1536
  };
1512
1537
  }
1538
+ /**
1539
+ * @internal Push an additional guard onto this node. Effective enforcement
1540
+ * is the AND of `_guard` and every guard pushed via this hook — any one
1541
+ * rejecting throws {@link GuardDenied}. Returns a disposer that removes
1542
+ * the pushed guard. Multiple guards may be stacked simultaneously.
1543
+ *
1544
+ * Used by `policyEnforcer({ mode: "enforce" })` (roadmap §9.2) to overlay
1545
+ * runtime constraint enforcement onto an existing graph without rebuilding
1546
+ * its nodes. Pre-1.0 internal API; not part of the public surface.
1547
+ *
1548
+ * **Identity semantics:** guards are tracked in a `Set`, so pushing the
1549
+ * same `NodeGuard` reference twice is a single registration. Wrap each
1550
+ * push in a unique closure if independent stacking is needed.
1551
+ *
1552
+ * **Iteration order:** insertion-ordered (`Set` semantics). Determinism
1553
+ * follows from single-threaded JS execution; nested re-entry from inside
1554
+ * a guard body (push/pop while iterating) is undefined-but-survivable.
1555
+ */
1556
+ _pushGuard(guard) {
1557
+ if (this._extraGuards == null) this._extraGuards = /* @__PURE__ */ new Set();
1558
+ this._extraGuards.add(guard);
1559
+ return () => {
1560
+ this._extraGuards?.delete(guard);
1561
+ if (this._extraGuards?.size === 0) this._extraGuards = void 0;
1562
+ };
1563
+ }
1513
1564
  allowsObserve(actor) {
1514
- if (this._guard == null) return true;
1515
- return this._guard(normalizeActor(actor), "observe");
1565
+ if (this._guard == null && this._extraGuards == null) return true;
1566
+ const a = normalizeActor(actor);
1567
+ if (this._guard != null && !this._guard(a, "observe")) return false;
1568
+ if (this._extraGuards != null) {
1569
+ for (const eg of this._extraGuards) {
1570
+ if (!eg(a, "observe")) return false;
1571
+ }
1572
+ }
1573
+ return true;
1516
1574
  }
1517
1575
  // --- Guard helper ---
1518
1576
  _checkGuard(options) {
1519
- if (options?.internal || this._guard == null) return;
1577
+ if (options?.internal) return;
1578
+ const hasGuard = this._guard != null || this._extraGuards != null;
1579
+ const hasActor = options?.actor != null;
1580
+ if (!hasGuard && !hasActor) return;
1520
1581
  const actor = normalizeActor(options?.actor);
1521
1582
  const action2 = options?.delivery === "signal" ? "signal" : "write";
1522
- if (!this._guard(actor, action2)) {
1583
+ if (this._guard != null && !this._guard(actor, action2)) {
1523
1584
  throw new GuardDenied({ actor, action: action2, nodeName: this.name });
1524
1585
  }
1586
+ if (this._extraGuards != null) {
1587
+ for (const eg of this._extraGuards) {
1588
+ if (!eg(actor, action2)) {
1589
+ throw new GuardDenied({ actor, action: action2, nodeName: this.name });
1590
+ }
1591
+ }
1592
+ }
1525
1593
  this._lastMutation = { actor, timestamp_ns: wallClockNs() };
1526
1594
  }
1527
1595
  // --- Public transport ---
@@ -3045,10 +3113,6 @@ function SagaHandler(cqrsName, sagaName, eventNames) {
3045
3113
  };
3046
3114
  }
3047
3115
 
3048
- // src/extra/sources.ts
3049
- var import_node_fs = require("fs");
3050
- var import_node_path = require("path");
3051
-
3052
3116
  // src/extra/cron.ts
3053
3117
  function parseField(field, min, max) {
3054
3118
  const result = /* @__PURE__ */ new Set();
@@ -3186,6 +3250,72 @@ function fromTimer(ms, opts) {
3186
3250
  return cleanup;
3187
3251
  }, sourceOpts(rest));
3188
3252
  }
3253
+ function fromRaf(opts) {
3254
+ const { signal, ...rest } = opts ?? {};
3255
+ return producer((a) => {
3256
+ let done = false;
3257
+ let rafId;
3258
+ let fallbackTimer;
3259
+ let abortListenerAdded = false;
3260
+ let visibilityListenerAdded = false;
3261
+ const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : void 0;
3262
+ const caf = typeof cancelAnimationFrame === "function" ? cancelAnimationFrame : void 0;
3263
+ const doc = typeof document !== "undefined" ? document : void 0;
3264
+ const clearPending = () => {
3265
+ if (rafId !== void 0 && caf) caf(rafId);
3266
+ if (fallbackTimer !== void 0) clearTimeout(fallbackTimer);
3267
+ rafId = void 0;
3268
+ fallbackTimer = void 0;
3269
+ };
3270
+ const cleanup = () => {
3271
+ done = true;
3272
+ clearPending();
3273
+ if (abortListenerAdded) {
3274
+ signal?.removeEventListener("abort", onAbort);
3275
+ abortListenerAdded = false;
3276
+ }
3277
+ if (visibilityListenerAdded && doc) {
3278
+ doc.removeEventListener("visibilitychange", onVisibilityChange);
3279
+ visibilityListenerAdded = false;
3280
+ }
3281
+ };
3282
+ const onAbort = () => {
3283
+ if (done) return;
3284
+ cleanup();
3285
+ a.down([[ERROR, signal.reason]]);
3286
+ };
3287
+ const tick = (now) => {
3288
+ if (done) return;
3289
+ a.emit(now);
3290
+ scheduleNext();
3291
+ };
3292
+ const scheduleNext = () => {
3293
+ if (done) return;
3294
+ if (raf && (!doc || doc.visibilityState !== "hidden")) {
3295
+ rafId = raf(tick);
3296
+ } else {
3297
+ fallbackTimer = setTimeout(() => tick(performance.now()), 16);
3298
+ }
3299
+ };
3300
+ const onVisibilityChange = () => {
3301
+ if (done) return;
3302
+ clearPending();
3303
+ scheduleNext();
3304
+ };
3305
+ if (signal?.aborted) {
3306
+ onAbort();
3307
+ return cleanup;
3308
+ }
3309
+ signal?.addEventListener("abort", onAbort, { once: true });
3310
+ abortListenerAdded = signal !== void 0;
3311
+ if (doc && raf) {
3312
+ doc.addEventListener("visibilitychange", onVisibilityChange);
3313
+ visibilityListenerAdded = true;
3314
+ }
3315
+ scheduleNext();
3316
+ return cleanup;
3317
+ }, sourceOpts(rest));
3318
+ }
3189
3319
  function fromCron(expr, opts) {
3190
3320
  const schedule = parseCron(expr);
3191
3321
  const { tickMs: tickOpt, output, ...rest } = opts ?? {};
@@ -3220,99 +3350,6 @@ function fromEvent(target, type, opts) {
3220
3350
  return () => target.removeEventListener(type, handler, options);
3221
3351
  }, sourceOpts(rest));
3222
3352
  }
3223
- function fromFSWatch(paths, opts) {
3224
- const list = Array.isArray(paths) ? paths : [paths];
3225
- if (list.length === 0) {
3226
- throw new RangeError("fromFSWatch expects at least one path");
3227
- }
3228
- const { recursive = true, debounce: debounce2 = 100, include, exclude, ...rest } = opts ?? {};
3229
- const includePatterns = include?.map(globToRegExp) ?? [];
3230
- const excludePatterns = (exclude ?? ["**/node_modules/**", "**/.git/**", "**/dist/**"]).map(
3231
- globToRegExp
3232
- );
3233
- return producer((a) => {
3234
- const pending = /* @__PURE__ */ new Map();
3235
- const watchers = [];
3236
- let stopped = false;
3237
- let terminalEmitted = false;
3238
- let generation = 0;
3239
- const closeWatchers = () => {
3240
- for (const watcher of watchers.splice(0)) watcher.close();
3241
- };
3242
- const emitError = (err) => {
3243
- if (terminalEmitted) return;
3244
- terminalEmitted = true;
3245
- stopped = true;
3246
- if (timer !== void 0) clearTimeout(timer);
3247
- timer = void 0;
3248
- pending.clear();
3249
- closeWatchers();
3250
- a.down([[ERROR, err]]);
3251
- };
3252
- let timer;
3253
- const flush = (token) => {
3254
- timer = void 0;
3255
- if (stopped || terminalEmitted) return;
3256
- if (pending.size === 0) return;
3257
- const batchMessages = [];
3258
- for (const evt of pending.values()) batchMessages.push([DATA, evt]);
3259
- pending.clear();
3260
- if (stopped || terminalEmitted || token !== generation) return;
3261
- a.down(batchMessages);
3262
- };
3263
- try {
3264
- for (const basePath of list) {
3265
- const watcher = (0, import_node_fs.watch)(
3266
- basePath,
3267
- { recursive },
3268
- (eventType, fileName) => {
3269
- if (stopped || terminalEmitted) return;
3270
- if (fileName == null) return;
3271
- const rel = String(fileName).replaceAll("\\", "/");
3272
- const abs = (0, import_node_path.resolve)(basePath, String(fileName));
3273
- const normalized = abs.replaceAll("\\", "/");
3274
- const root = (0, import_node_path.resolve)(basePath).replaceAll("\\", "/");
3275
- const relForMatch = rel.startsWith("./") ? rel.slice(2) : rel;
3276
- const included = includePatterns.length === 0 || matchesAnyPattern(normalized, includePatterns) || matchesAnyPattern(relForMatch, includePatterns);
3277
- if (!included) return;
3278
- const excluded = matchesAnyPattern(normalized, excludePatterns) || matchesAnyPattern(relForMatch, excludePatterns);
3279
- if (excluded) return;
3280
- let kind = "change";
3281
- if (eventType === "rename") {
3282
- try {
3283
- kind = (0, import_node_fs.existsSync)(normalized) ? "create" : "delete";
3284
- } catch {
3285
- kind = "rename";
3286
- }
3287
- }
3288
- pending.set(normalized, {
3289
- type: kind,
3290
- path: normalized,
3291
- root,
3292
- relative_path: relForMatch,
3293
- timestamp_ns: wallClockNs()
3294
- });
3295
- if (timer !== void 0) clearTimeout(timer);
3296
- const token = generation;
3297
- timer = setTimeout(() => flush(token), debounce2);
3298
- }
3299
- );
3300
- watcher.on("error", (err) => emitError(err));
3301
- watchers.push(watcher);
3302
- }
3303
- } catch (err) {
3304
- emitError(err);
3305
- }
3306
- return () => {
3307
- stopped = true;
3308
- generation += 1;
3309
- if (timer !== void 0) clearTimeout(timer);
3310
- timer = void 0;
3311
- closeWatchers();
3312
- pending.clear();
3313
- };
3314
- }, sourceOpts(rest));
3315
- }
3316
3353
  function fromIter(iterable, opts) {
3317
3354
  return producer((a) => {
3318
3355
  let cancelled = false;
@@ -4527,6 +4564,200 @@ var RingBuffer = class {
4527
4564
  }
4528
4565
  };
4529
4566
 
4567
+ // src/graph/explain.ts
4568
+ function explainPath(described, from, to, opts = {}) {
4569
+ const fromExists = from in described.nodes;
4570
+ const toExists = to in described.nodes;
4571
+ if (!fromExists) return makeFailure(from, to, "no-such-from");
4572
+ if (!toExists) return makeFailure(from, to, "no-such-to");
4573
+ const maxDepth = opts.maxDepth;
4574
+ if (maxDepth != null && (!Number.isInteger(maxDepth) || maxDepth < 0)) {
4575
+ throw new Error(`explainPath: maxDepth must be an integer >= 0`);
4576
+ }
4577
+ if (from === to) {
4578
+ if (opts.findCycle === true) {
4579
+ const cycle = findShortestCycle(described, from, opts);
4580
+ if (cycle != null) return cycle;
4581
+ }
4582
+ const step = buildStep(from, described.nodes[from], 0, opts);
4583
+ return makeSuccess(from, to, [step]);
4584
+ }
4585
+ if (maxDepth === 0) return makeFailure(from, to, "no-path");
4586
+ const result = bfsShortestPath(described, from, to, maxDepth);
4587
+ if (!result.found) {
4588
+ return makeFailure(from, to, result.truncated ? "max-depth-exceeded" : "no-path");
4589
+ }
4590
+ return makeSuccess(from, to, materializeSteps(described, result.pathOrder, opts));
4591
+ }
4592
+ function bfsShortestPath(described, from, to, maxDepth) {
4593
+ const pred = /* @__PURE__ */ new Map();
4594
+ const queue = [{ path: to, depth: 0 }];
4595
+ const visited = /* @__PURE__ */ new Set([to]);
4596
+ let head = 0;
4597
+ let truncated = false;
4598
+ while (head < queue.length) {
4599
+ const cur = queue[head++];
4600
+ if (cur.path === from) break;
4601
+ if (maxDepth != null && cur.depth >= maxDepth) {
4602
+ const node3 = described.nodes[cur.path];
4603
+ if (node3?.deps && node3.deps.length > 0) truncated = true;
4604
+ continue;
4605
+ }
4606
+ const node2 = described.nodes[cur.path];
4607
+ if (node2 == null) continue;
4608
+ const deps = node2.deps ?? [];
4609
+ const slots = /* @__PURE__ */ new Map();
4610
+ for (let i = 0; i < deps.length; i++) {
4611
+ const dep = deps[i];
4612
+ if (!dep) continue;
4613
+ let arr = slots.get(dep);
4614
+ if (arr == null) {
4615
+ arr = [];
4616
+ slots.set(dep, arr);
4617
+ }
4618
+ arr.push(i);
4619
+ }
4620
+ for (const [dep, indices] of slots) {
4621
+ if (visited.has(dep)) continue;
4622
+ visited.add(dep);
4623
+ pred.set(dep, { from: cur.path, depIndices: indices });
4624
+ queue.push({ path: dep, depth: cur.depth + 1 });
4625
+ }
4626
+ }
4627
+ if (!pred.has(from)) {
4628
+ return { found: false, pathOrder: [], truncated };
4629
+ }
4630
+ const pathOrder = [{ path: from }];
4631
+ let cursor = from;
4632
+ while (cursor !== to) {
4633
+ const p = pred.get(cursor);
4634
+ if (p == null) return { found: false, pathOrder: [], truncated: false };
4635
+ pathOrder[pathOrder.length - 1].depIndices = p.depIndices;
4636
+ pathOrder.push({ path: p.from });
4637
+ cursor = p.from;
4638
+ }
4639
+ return { found: true, pathOrder, truncated: false };
4640
+ }
4641
+ function findShortestCycle(described, start, opts) {
4642
+ const startNode = described.nodes[start];
4643
+ if (startNode == null) return null;
4644
+ const startDeps = startNode.deps ?? [];
4645
+ const selfSlots = [];
4646
+ for (let i = 0; i < startDeps.length; i++) if (startDeps[i] === start) selfSlots.push(i);
4647
+ if (selfSlots.length > 0) {
4648
+ const step0 = buildStep(start, startNode, 0, opts);
4649
+ step0.dep_index = selfSlots[0];
4650
+ const step1 = buildStep(start, startNode, 1, opts);
4651
+ return makeSuccess(start, start, [step0, step1]);
4652
+ }
4653
+ let best = null;
4654
+ for (let i = 0; i < startDeps.length; i++) {
4655
+ const dep = startDeps[i];
4656
+ if (!dep || dep === start) continue;
4657
+ const sub = bfsShortestPath(described, dep, start, opts.maxDepth);
4658
+ if (!sub.found) continue;
4659
+ if (best == null || sub.pathOrder.length < best.pathOrder.length) {
4660
+ best = sub;
4661
+ best = {
4662
+ found: true,
4663
+ pathOrder: [{ path: start, depIndices: [i] }, ...sub.pathOrder],
4664
+ truncated: false
4665
+ };
4666
+ }
4667
+ }
4668
+ if (best == null) return null;
4669
+ return makeSuccess(start, start, materializeSteps(described, best.pathOrder, opts));
4670
+ }
4671
+ function materializeSteps(described, pathOrder, opts) {
4672
+ return pathOrder.map((entry, i) => {
4673
+ const node2 = described.nodes[entry.path];
4674
+ const step = buildStep(entry.path, node2, i, opts);
4675
+ if (entry.depIndices != null && entry.depIndices.length > 0) {
4676
+ step.dep_index = entry.depIndices[0];
4677
+ if (entry.depIndices.length > 1) step.dep_indices = [...entry.depIndices];
4678
+ }
4679
+ return step;
4680
+ });
4681
+ }
4682
+ function buildStep(path, node2, hop, opts) {
4683
+ const step = {
4684
+ path,
4685
+ type: node2.type,
4686
+ hop
4687
+ };
4688
+ if (node2.status !== void 0) step.status = node2.status;
4689
+ if ("value" in node2) step.value = node2.value;
4690
+ if (node2.v != null) step.v = node2.v;
4691
+ const annotation = opts.annotations?.get(path) ?? node2.reason;
4692
+ if (annotation != null) step.reason = annotation;
4693
+ const lastMutation = opts.lastMutations?.get(path) ?? node2.lastMutation;
4694
+ if (lastMutation != null) step.lastMutation = lastMutation;
4695
+ return step;
4696
+ }
4697
+ function makeSuccess(from, to, steps) {
4698
+ return finalize(from, to, true, "ok", steps);
4699
+ }
4700
+ function makeFailure(from, to, reason) {
4701
+ return finalize(from, to, false, reason, []);
4702
+ }
4703
+ function finalize(from, to, found, reason, steps) {
4704
+ const text = renderChain(from, to, found, reason, steps);
4705
+ return {
4706
+ from,
4707
+ to,
4708
+ found,
4709
+ reason,
4710
+ steps,
4711
+ text,
4712
+ toJSON() {
4713
+ return { from, to, found, reason, steps };
4714
+ }
4715
+ };
4716
+ }
4717
+ function renderChain(from, to, found, reason, steps) {
4718
+ if (!found) {
4719
+ switch (reason) {
4720
+ case "no-such-from":
4721
+ return `explainPath: no node named "${from}"`;
4722
+ case "no-such-to":
4723
+ return `explainPath: no node named "${to}"`;
4724
+ case "max-depth-exceeded":
4725
+ return `explainPath: no path from "${from}" to "${to}" within maxDepth`;
4726
+ default:
4727
+ return `explainPath: no path from "${from}" to "${to}"`;
4728
+ }
4729
+ }
4730
+ const lines = [`Causal path: ${from} \u2192 ${to} (${steps.length} step(s))`];
4731
+ for (const step of steps) {
4732
+ const arrow = step.hop === 0 ? "\xB7" : "\u2193";
4733
+ const head = ` ${arrow} ${step.path} (${step.type}${step.status ? `/${step.status}` : ""})`;
4734
+ lines.push(head);
4735
+ if ("value" in step) {
4736
+ lines.push(` value: ${formatValue(step.value)}`);
4737
+ }
4738
+ if (step.reason != null) {
4739
+ lines.push(` reason: ${step.reason}`);
4740
+ }
4741
+ if (step.lastMutation != null) {
4742
+ const a = step.lastMutation.actor;
4743
+ lines.push(` actor: ${a.type}${a.id ? `:${a.id}` : ""}`);
4744
+ }
4745
+ }
4746
+ return lines.join("\n");
4747
+ }
4748
+ function formatValue(v) {
4749
+ if (v === void 0) return "<sentinel>";
4750
+ if (v === null) return "null";
4751
+ if (typeof v === "string") return JSON.stringify(v);
4752
+ if (typeof v === "number" || typeof v === "boolean" || typeof v === "bigint") return String(v);
4753
+ try {
4754
+ const s = JSON.stringify(v);
4755
+ return s.length > 80 ? `${s.slice(0, 77)}...` : s;
4756
+ } catch {
4757
+ return String(v);
4758
+ }
4759
+ }
4760
+
4530
4761
  // src/extra/utils/sizeof.ts
4531
4762
  var OVERHEAD = {
4532
4763
  object: 56,
@@ -5160,6 +5391,20 @@ var Graph = class _Graph {
5160
5391
  _parent = void 0;
5161
5392
  _storageDisposers = /* @__PURE__ */ new Set();
5162
5393
  _disposers = /* @__PURE__ */ new Set();
5394
+ /**
5395
+ * @internal Lazy `TopologyEvent` producer. Created on first `.topology`
5396
+ * access. Zero cost until something subscribes — producer fn only runs when
5397
+ * the first sink attaches, registering one handler into
5398
+ * {@link Graph._topologyEmitters}.
5399
+ */
5400
+ _topology;
5401
+ /**
5402
+ * @internal Active emit handlers for the topology producer. Each entry is
5403
+ * the closure registered by the producer fn on activation; cleared on
5404
+ * deactivation. `_emitTopology` broadcasts through every entry (there is at
5405
+ * most one per activation cycle of the producer).
5406
+ */
5407
+ _topologyEmitters = /* @__PURE__ */ new Set();
5163
5408
  /**
5164
5409
  * @param name - Non-empty graph id (must not contain `::` and must not
5165
5410
  * equal the reserved meta segment `__meta__`).
@@ -5199,6 +5444,55 @@ var Graph = class _Graph {
5199
5444
  return out;
5200
5445
  }
5201
5446
  // ——————————————————————————————————————————————————————————————
5447
+ // Topology companion (structural-change event stream)
5448
+ // ——————————————————————————————————————————————————————————————
5449
+ /**
5450
+ * Reactive stream of structural changes to this graph's own registry
5451
+ * (add / mount / remove). Value mutations live on `observe()`; this
5452
+ * companion only fires when the topology shape changes.
5453
+ *
5454
+ * Lazy: the underlying node is created on first access and activates when
5455
+ * something subscribes. No emission replay — late subscribers do not
5456
+ * receive historical events and should snapshot via {@link Graph.describe}
5457
+ * before listening for incremental changes. Events that fire while the
5458
+ * producer has zero subscribers are dropped (no retention).
5459
+ *
5460
+ * Own-graph only: a parent's `topology` does NOT emit for structural
5461
+ * changes inside a mounted child. Transitive consumers subscribe to each
5462
+ * child's topology separately (recurse through `topology`'s own "added"
5463
+ * events with `nodeKind: "mount"` to discover new children).
5464
+ *
5465
+ * See {@link TopologyEvent} for payload shape.
5466
+ *
5467
+ * @category observability
5468
+ */
5469
+ get topology() {
5470
+ if (this._topology == null) {
5471
+ this._topology = producer(
5472
+ (actions) => {
5473
+ const handler = (event) => {
5474
+ actions.emit(event);
5475
+ };
5476
+ this._topologyEmitters.add(handler);
5477
+ return () => {
5478
+ this._topologyEmitters.delete(handler);
5479
+ };
5480
+ },
5481
+ { name: `${this.name}_topology` }
5482
+ );
5483
+ }
5484
+ return this._topology;
5485
+ }
5486
+ /**
5487
+ * @internal Fire a {@link TopologyEvent} to every active subscriber of
5488
+ * `this.topology`. No-op when the topology node has never been accessed or
5489
+ * currently has no sinks — zero cost for graphs nobody observes.
5490
+ */
5491
+ _emitTopology(event) {
5492
+ if (this._topology == null || this._topologyEmitters.size === 0) return;
5493
+ for (const h of this._topologyEmitters) h(event);
5494
+ }
5495
+ // ——————————————————————————————————————————————————————————————
5202
5496
  // Node registry
5203
5497
  // ——————————————————————————————————————————————————————————————
5204
5498
  /**
@@ -5228,6 +5522,7 @@ var Graph = class _Graph {
5228
5522
  }
5229
5523
  this._nodes.set(name, node2);
5230
5524
  this._nodeToName.set(node2, name);
5525
+ this._emitTopology({ kind: "added", name, nodeKind: "node" });
5231
5526
  return node2;
5232
5527
  }
5233
5528
  /**
@@ -5268,22 +5563,23 @@ var Graph = class _Graph {
5268
5563
  assertRegisterableName(name, this.name, "remove");
5269
5564
  const child = this._mounts.get(name);
5270
5565
  if (child) {
5271
- const audit2 = { kind: "mount", nodes: [], mounts: [] };
5566
+ const audit3 = { kind: "mount", nodes: [], mounts: [] };
5272
5567
  const targets = [];
5273
5568
  child._collectObserveTargets("", targets);
5274
5569
  for (const [p, n] of targets) {
5275
5570
  if (!p.includes(`${PATH_SEP}${GRAPH_META_SEGMENT}${PATH_SEP}`)) {
5276
- audit2.nodes.push(p);
5571
+ audit3.nodes.push(p);
5277
5572
  }
5278
5573
  void n;
5279
5574
  }
5280
- audit2.nodes.sort();
5281
- audit2.mounts.push(name);
5282
- audit2.mounts.push(...child._collectSubgraphs(`${name}${PATH_SEP}`));
5575
+ audit3.nodes.sort();
5576
+ audit3.mounts.push(name);
5577
+ audit3.mounts.push(...child._collectSubgraphs(`${name}${PATH_SEP}`));
5283
5578
  this._mounts.delete(name);
5284
5579
  child._parent = void 0;
5285
5580
  teardownMountedGraph(child);
5286
- return audit2;
5581
+ this._emitTopology({ kind: "removed", name, nodeKind: "mount", audit: audit3 });
5582
+ return audit3;
5287
5583
  }
5288
5584
  const node2 = this._nodes.get(name);
5289
5585
  if (!node2) {
@@ -5292,7 +5588,9 @@ var Graph = class _Graph {
5292
5588
  this._nodes.delete(name);
5293
5589
  this._nodeToName.delete(node2);
5294
5590
  node2.down([[TEARDOWN]], { internal: true });
5295
- return { kind: "node", nodes: [name], mounts: [] };
5591
+ const audit2 = { kind: "node", nodes: [name], mounts: [] };
5592
+ this._emitTopology({ kind: "removed", name, nodeKind: "node", audit: audit2 });
5593
+ return audit2;
5296
5594
  }
5297
5595
  /**
5298
5596
  * Bulk remove — invokes {@link Graph.remove} for every local name matching
@@ -5521,6 +5819,7 @@ var Graph = class _Graph {
5521
5819
  }
5522
5820
  this._mounts.set(name, child);
5523
5821
  child._parent = this;
5822
+ this._emitTopology({ kind: "added", name, nodeKind: "mount" });
5524
5823
  return child;
5525
5824
  }
5526
5825
  /**
@@ -5811,6 +6110,33 @@ var Graph = class _Graph {
5811
6110
  }
5812
6111
  return reachable(this.describe(), from, direction, opts);
5813
6112
  }
6113
+ /**
6114
+ * Causal walkback: shortest dep-chain from `from` to `to`, enriched with
6115
+ * each node's value, status, last-mutation actor, and reasoning annotation
6116
+ * from {@link Graph.trace}. Wraps {@link explainPath} (roadmap §9.2).
6117
+ *
6118
+ * @param from - Upstream node (the cause).
6119
+ * @param to - Downstream node (the effect).
6120
+ * @param opts - Optional `maxDepth` and `findCycle`. When `findCycle:true`
6121
+ * and `from === to`, returns the shortest cycle through other nodes
6122
+ * (useful for diagnosing feedback loops, COMPOSITION-GUIDE §7).
6123
+ * Annotations and lastMutations are collected automatically from the
6124
+ * live graph.
6125
+ */
6126
+ explain(from, to, opts) {
6127
+ const described = this.describe({ detail: "full" });
6128
+ const annotations = new Map(this._annotations);
6129
+ const lastMutations = /* @__PURE__ */ new Map();
6130
+ for (const [path, n] of Object.entries(described.nodes)) {
6131
+ if (n.lastMutation != null) lastMutations.set(path, n.lastMutation);
6132
+ }
6133
+ return explainPath(described, from, to, {
6134
+ ...opts?.maxDepth != null ? { maxDepth: opts.maxDepth } : {},
6135
+ ...opts?.findCycle === true ? { findCycle: true } : {},
6136
+ annotations,
6137
+ lastMutations
6138
+ });
6139
+ }
5814
6140
  /**
5815
6141
  * @internal Collect all qualified paths in this graph tree matching a
5816
6142
  * glob pattern. Used by scoped autoCheckpoint subscription.
@@ -6489,7 +6815,7 @@ var Graph = class _Graph {
6489
6815
  return;
6490
6816
  }
6491
6817
  const nextSeq = s.seq + 1;
6492
- const timestamp_ns = monotonicNs();
6818
+ const timestamp_ns = wallClockNs();
6493
6819
  const isFirst = s.lastSnapshot == null;
6494
6820
  const shouldCompact = isFirst || nextSeq % s.compactEvery === 0;
6495
6821
  const record = shouldCompact ? {
@@ -7263,18 +7589,67 @@ __export(graph_exports, {
7263
7589
  JsonCodec: () => JsonCodec,
7264
7590
  SIZEOF_OVERHEAD: () => OVERHEAD,
7265
7591
  SIZEOF_SYMBOL: () => SIZEOF_SYMBOL,
7592
+ SNAPSHOT_VERSION: () => SNAPSHOT_VERSION,
7266
7593
  createDagCborCodec: () => createDagCborCodec,
7267
7594
  createDagCborZstdCodec: () => createDagCborZstdCodec,
7268
7595
  decodeEnvelope: () => decodeEnvelope,
7269
7596
  diffForWAL: () => diffForWAL,
7270
7597
  encodeEnvelope: () => encodeEnvelope,
7598
+ explainPath: () => explainPath,
7271
7599
  graphProfile: () => graphProfile,
7272
7600
  reachable: () => reachable,
7273
7601
  registerBuiltinCodecs: () => registerBuiltinCodecs,
7274
7602
  replayWAL: () => replayWAL,
7275
- sizeof: () => sizeof
7603
+ sizeof: () => sizeof,
7604
+ watchTopologyTree: () => watchTopologyTree
7276
7605
  });
7277
7606
 
7607
+ // src/graph/topology-tree.ts
7608
+ function watchTopologyTree(graph, cb) {
7609
+ const subs = /* @__PURE__ */ new Map();
7610
+ const wire = (g, prefix) => {
7611
+ if (subs.has(g)) return;
7612
+ const placeholder = { off: () => {
7613
+ }, prefix };
7614
+ subs.set(g, placeholder);
7615
+ const off = g.topology.subscribe((msgs) => {
7616
+ for (const m of msgs) {
7617
+ if (m[0] !== DATA) continue;
7618
+ const event = m[1];
7619
+ cb(event, g, prefix);
7620
+ if (event.kind === "added" && event.nodeKind === "mount") {
7621
+ const child = g._mounts.get(event.name);
7622
+ if (child instanceof Graph) {
7623
+ const childPrefix = `${prefix}${event.name}::`;
7624
+ wire(child, childPrefix);
7625
+ }
7626
+ } else if (event.kind === "removed" && event.nodeKind === "mount") {
7627
+ const removedPrefix = `${prefix}${event.name}::`;
7628
+ for (const [trackedGraph, trackedEntry] of Array.from(subs.entries())) {
7629
+ if (trackedGraph === graph) continue;
7630
+ if (trackedEntry.prefix.startsWith(removedPrefix)) {
7631
+ trackedEntry.off();
7632
+ subs.delete(trackedGraph);
7633
+ }
7634
+ }
7635
+ }
7636
+ }
7637
+ });
7638
+ placeholder.off = off;
7639
+ for (const [mountName, child] of g._mounts) {
7640
+ if (child instanceof Graph) {
7641
+ const childPrefix = `${prefix}${mountName}::`;
7642
+ wire(child, childPrefix);
7643
+ }
7644
+ }
7645
+ };
7646
+ wire(graph, "");
7647
+ return () => {
7648
+ for (const entry of subs.values()) entry.off();
7649
+ subs.clear();
7650
+ };
7651
+ }
7652
+
7278
7653
  // src/patterns/_internal.ts
7279
7654
  function emitToMeta(metaNode, value) {
7280
7655
  if (metaNode == null) return;
@@ -8368,6 +8743,7 @@ __export(extra_exports, {
8368
8743
  fromPromise: () => fromPromise,
8369
8744
  fromPulsar: () => fromPulsar,
8370
8745
  fromRabbitMQ: () => fromRabbitMQ,
8746
+ fromRaf: () => fromRaf,
8371
8747
  fromRedisStream: () => fromRedisStream,
8372
8748
  fromSSE: () => fromSSE,
8373
8749
  fromSqlite: () => fromSqlite,
@@ -14142,37 +14518,140 @@ function reactiveList(initial, options = {}) {
14142
14518
  };
14143
14519
  }
14144
14520
 
14145
- // src/extra/storage.ts
14146
- var import_node_crypto = require("crypto");
14147
- var import_node_fs2 = require("fs");
14148
- var import_node_path2 = require("path");
14149
- var import_node_sqlite = require("sqlite");
14150
- function sortJsonValue2(value) {
14151
- if (value === null || typeof value !== "object") return value;
14152
- if (Array.isArray(value)) return value.map(sortJsonValue2);
14153
- const obj = value;
14154
- const keys = Object.keys(obj).sort();
14155
- const out = {};
14156
- for (const k of keys) out[k] = sortJsonValue2(obj[k]);
14157
- return out;
14158
- }
14159
- function stableJsonString(data) {
14160
- return JSON.stringify(sortJsonValue2(data), void 0, 0);
14521
+ // src/extra/sources-fs.ts
14522
+ var import_node_fs = require("node:fs");
14523
+ var import_node_path = require("node:path");
14524
+ function sourceOpts4(opts) {
14525
+ return { describeKind: "producer", ...opts };
14161
14526
  }
14162
- function memoryStorage() {
14163
- const data = /* @__PURE__ */ new Map();
14164
- return {
14165
- save(key, record) {
14166
- data.set(key, JSON.parse(JSON.stringify(record)));
14167
- },
14168
- load(key) {
14169
- const v = data.get(key);
14170
- return v === void 0 ? null : JSON.parse(JSON.stringify(v));
14171
- },
14172
- clear(key) {
14173
- data.delete(key);
14174
- }
14175
- };
14527
+ function fromFSWatch(paths, opts) {
14528
+ const list = Array.isArray(paths) ? paths : [paths];
14529
+ if (list.length === 0) {
14530
+ throw new RangeError("fromFSWatch expects at least one path");
14531
+ }
14532
+ const { recursive = true, debounce: debounce2 = 100, include, exclude, ...rest } = opts ?? {};
14533
+ const includePatterns = include?.map(globToRegExp) ?? [];
14534
+ const excludePatterns = (exclude ?? ["**/node_modules/**", "**/.git/**", "**/dist/**"]).map(
14535
+ globToRegExp
14536
+ );
14537
+ return producer((a) => {
14538
+ const pending = /* @__PURE__ */ new Map();
14539
+ const watchers = [];
14540
+ let stopped = false;
14541
+ let terminalEmitted = false;
14542
+ let generation = 0;
14543
+ const closeWatchers = () => {
14544
+ for (const watcher of watchers.splice(0)) watcher.close();
14545
+ };
14546
+ const emitError = (err) => {
14547
+ if (terminalEmitted) return;
14548
+ terminalEmitted = true;
14549
+ stopped = true;
14550
+ if (timer !== void 0) clearTimeout(timer);
14551
+ timer = void 0;
14552
+ pending.clear();
14553
+ closeWatchers();
14554
+ a.down([[ERROR, err]]);
14555
+ };
14556
+ let timer;
14557
+ const flush = (token) => {
14558
+ timer = void 0;
14559
+ if (stopped || terminalEmitted) return;
14560
+ if (pending.size === 0) return;
14561
+ const batchMessages = [];
14562
+ for (const evt of pending.values()) batchMessages.push([DATA, evt]);
14563
+ pending.clear();
14564
+ if (stopped || terminalEmitted || token !== generation) return;
14565
+ a.down(batchMessages);
14566
+ };
14567
+ try {
14568
+ for (const basePath of list) {
14569
+ const watcher = (0, import_node_fs.watch)(
14570
+ basePath,
14571
+ { recursive },
14572
+ (eventType, fileName) => {
14573
+ if (stopped || terminalEmitted) return;
14574
+ if (fileName == null) return;
14575
+ const rel = String(fileName).replaceAll("\\", "/");
14576
+ const abs = (0, import_node_path.resolve)(basePath, String(fileName));
14577
+ const normalized = abs.replaceAll("\\", "/");
14578
+ const root = (0, import_node_path.resolve)(basePath).replaceAll("\\", "/");
14579
+ const relForMatch = rel.startsWith("./") ? rel.slice(2) : rel;
14580
+ const included = includePatterns.length === 0 || matchesAnyPattern(normalized, includePatterns) || matchesAnyPattern(relForMatch, includePatterns);
14581
+ if (!included) return;
14582
+ const excluded = matchesAnyPattern(normalized, excludePatterns) || matchesAnyPattern(relForMatch, excludePatterns);
14583
+ if (excluded) return;
14584
+ let kind = "change";
14585
+ if (eventType === "rename") {
14586
+ try {
14587
+ kind = (0, import_node_fs.existsSync)(normalized) ? "create" : "delete";
14588
+ } catch {
14589
+ kind = "rename";
14590
+ }
14591
+ }
14592
+ pending.set(normalized, {
14593
+ type: kind,
14594
+ path: normalized,
14595
+ root,
14596
+ relative_path: relForMatch,
14597
+ timestamp_ns: wallClockNs()
14598
+ });
14599
+ if (timer !== void 0) clearTimeout(timer);
14600
+ const token = generation;
14601
+ timer = setTimeout(() => flush(token), debounce2);
14602
+ }
14603
+ );
14604
+ watcher.on("error", (err) => emitError(err));
14605
+ watchers.push(watcher);
14606
+ }
14607
+ } catch (err) {
14608
+ emitError(err);
14609
+ }
14610
+ return () => {
14611
+ stopped = true;
14612
+ generation += 1;
14613
+ if (timer !== void 0) clearTimeout(timer);
14614
+ timer = void 0;
14615
+ closeWatchers();
14616
+ pending.clear();
14617
+ };
14618
+ }, sourceOpts4(rest));
14619
+ }
14620
+
14621
+ // src/extra/storage.ts
14622
+ var import_node_crypto = require("node:crypto");
14623
+ var import_node_fs2 = require("node:fs");
14624
+ var import_node_path2 = require("node:path");
14625
+ var import_node_sqlite = require("node:sqlite");
14626
+ function sortJsonValue2(value) {
14627
+ if (value === null || typeof value !== "object") return value;
14628
+ if (Array.isArray(value)) return value.map(sortJsonValue2);
14629
+ const obj = value;
14630
+ const keys = Object.keys(obj).sort();
14631
+ const out = {};
14632
+ for (const k of keys) out[k] = sortJsonValue2(obj[k]);
14633
+ return out;
14634
+ }
14635
+ function stableJsonString(data) {
14636
+ return JSON.stringify(sortJsonValue2(data), void 0, 0);
14637
+ }
14638
+ function memoryStorage() {
14639
+ const data = /* @__PURE__ */ new Map();
14640
+ return {
14641
+ save(key, record) {
14642
+ data.set(key, JSON.parse(JSON.stringify(record)));
14643
+ },
14644
+ load(key) {
14645
+ const v = data.get(key);
14646
+ return v === void 0 ? null : JSON.parse(JSON.stringify(v));
14647
+ },
14648
+ clear(key) {
14649
+ data.delete(key);
14650
+ },
14651
+ list() {
14652
+ return [...data.keys()].sort();
14653
+ }
14654
+ };
14176
14655
  }
14177
14656
  function dictStorage(storage) {
14178
14657
  return {
@@ -14185,16 +14664,54 @@ function dictStorage(storage) {
14185
14664
  },
14186
14665
  clear(key) {
14187
14666
  delete storage[key];
14667
+ },
14668
+ list() {
14669
+ return Object.keys(storage).sort();
14188
14670
  }
14189
14671
  };
14190
14672
  }
14191
14673
  function fileStorage(dir) {
14674
+ const encoder = new TextEncoder();
14675
+ const decoder = new TextDecoder("utf-8", { fatal: true });
14192
14676
  const pathFor = (key) => {
14193
- const safe = key.replace(
14194
- /[^a-zA-Z0-9_-]/g,
14195
- (c) => `%${c.charCodeAt(0).toString(16).padStart(2, "0")}`
14196
- );
14197
- return (0, import_node_path2.join)(dir, `${safe}.json`);
14677
+ let out = "";
14678
+ for (const ch of key) {
14679
+ if (ch.length === 1 && /[a-zA-Z0-9_-]/.test(ch)) {
14680
+ out += ch;
14681
+ continue;
14682
+ }
14683
+ for (const byte of encoder.encode(ch)) {
14684
+ out += `%${byte.toString(16).padStart(2, "0")}`;
14685
+ }
14686
+ }
14687
+ return (0, import_node_path2.join)(dir, `${out}.json`);
14688
+ };
14689
+ const keyFromFilename = (filename) => {
14690
+ if (!filename.endsWith(".json")) return null;
14691
+ const stem = filename.slice(0, -".json".length);
14692
+ const bytes = [];
14693
+ const encodeAscii = (s) => {
14694
+ for (let i2 = 0; i2 < s.length; i2++) bytes.push(s.charCodeAt(i2));
14695
+ };
14696
+ let i = 0;
14697
+ while (i < stem.length) {
14698
+ const ch = stem[i];
14699
+ if (ch === "%" && i + 2 < stem.length) {
14700
+ const hex = stem.slice(i + 1, i + 3);
14701
+ if (/^[0-9a-f]{2}$/i.test(hex)) {
14702
+ bytes.push(Number.parseInt(hex, 16));
14703
+ i += 3;
14704
+ continue;
14705
+ }
14706
+ }
14707
+ encodeAscii(ch);
14708
+ i += 1;
14709
+ }
14710
+ try {
14711
+ return decoder.decode(new Uint8Array(bytes));
14712
+ } catch {
14713
+ return null;
14714
+ }
14198
14715
  };
14199
14716
  return {
14200
14717
  save(key, record) {
@@ -14231,6 +14748,21 @@ function fileStorage(dir) {
14231
14748
  } catch (e) {
14232
14749
  if (e.code !== "ENOENT") throw e;
14233
14750
  }
14751
+ },
14752
+ list() {
14753
+ try {
14754
+ const entries = (0, import_node_fs2.readdirSync)(dir);
14755
+ const keys = [];
14756
+ for (const entry of entries) {
14757
+ if (entry.startsWith(".")) continue;
14758
+ const k = keyFromFilename(entry);
14759
+ if (k !== null) keys.push(k);
14760
+ }
14761
+ return keys.sort();
14762
+ } catch (e) {
14763
+ if (e.code === "ENOENT") return [];
14764
+ throw e;
14765
+ }
14234
14766
  }
14235
14767
  };
14236
14768
  }
@@ -14253,6 +14785,10 @@ function sqliteStorage(path) {
14253
14785
  clear(key) {
14254
14786
  db.prepare(`DELETE FROM graphrefly_checkpoint WHERE k = ?`).run(key);
14255
14787
  },
14788
+ list() {
14789
+ const rows = db.prepare(`SELECT k FROM graphrefly_checkpoint ORDER BY k`).all();
14790
+ return rows.map((r) => r.k);
14791
+ },
14256
14792
  close() {
14257
14793
  try {
14258
14794
  db.close();
@@ -14902,17 +15438,32 @@ function workerSelf(target, opts) {
14902
15438
  // src/patterns/index.ts
14903
15439
  var patterns_exports = {};
14904
15440
  __export(patterns_exports, {
15441
+ SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
15442
+ SurfaceError: () => SurfaceError,
15443
+ accountability: () => audit_exports,
14905
15444
  ai: () => ai_exports,
15445
+ asSurfaceError: () => asSurfaceError,
14906
15446
  cqrs: () => cqrs_exports,
15447
+ createGraph: () => createGraph,
15448
+ deleteSnapshot: () => deleteSnapshot,
14907
15449
  demoShell: () => demo_shell_exports,
15450
+ diffSnapshots: () => diffSnapshots,
14908
15451
  domainTemplates: () => domain_templates_exports,
14909
15452
  graphspec: () => graphspec_exports,
15453
+ guarded: () => guarded_execution_exports,
14910
15454
  harness: () => harness_exports,
14911
15455
  layout: () => reactive_layout_exports,
15456
+ lens: () => lens_exports,
15457
+ listSnapshots: () => listSnapshots,
14912
15458
  memory: () => memory_exports,
14913
15459
  messaging: () => messaging_exports,
14914
15460
  orchestration: () => orchestration_exports,
14915
- reduction: () => reduction_exports
15461
+ reduction: () => reduction_exports,
15462
+ resilientPipeline: () => resilient_pipeline_exports,
15463
+ restoreSnapshot: () => restoreSnapshot,
15464
+ runReduction: () => runReduction,
15465
+ saveSnapshot: () => saveSnapshot,
15466
+ surface: () => surface_exports
14916
15467
  });
14917
15468
 
14918
15469
  // src/patterns/ai.ts
@@ -17950,44 +18501,458 @@ async function suggestStrategy(graph, problem, adapter, opts) {
17950
18501
  };
17951
18502
  }
17952
18503
 
17953
- // src/patterns/demo-shell.ts
17954
- var demo_shell_exports = {};
17955
- __export(demo_shell_exports, {
17956
- demoShell: () => demoShell
18504
+ // src/patterns/audit.ts
18505
+ var audit_exports = {};
18506
+ __export(audit_exports, {
18507
+ AuditTrailGraph: () => AuditTrailGraph,
18508
+ PolicyEnforcerGraph: () => PolicyEnforcerGraph,
18509
+ auditTrail: () => auditTrail,
18510
+ complianceSnapshot: () => complianceSnapshot,
18511
+ policyEnforcer: () => policyEnforcer,
18512
+ reactiveExplainPath: () => reactiveExplainPath
17957
18513
  });
17958
-
17959
- // src/patterns/reactive-layout/reactive-layout.ts
17960
- function isCJK(s) {
17961
- for (const ch of s) {
17962
- const c = ch.codePointAt(0);
17963
- if (c >= 19968 && c <= 40959 || // CJK Unified Ideographs
17964
- c >= 13312 && c <= 19903 || // CJK Extension A
17965
- c >= 12288 && c <= 12351 || // CJK Symbols and Punctuation
17966
- c >= 12352 && c <= 12447 || // Hiragana
17967
- c >= 12448 && c <= 12543 || // Katakana
17968
- c >= 44032 && c <= 55215 || // Hangul
17969
- c >= 65280 && c <= 65519) {
18514
+ function auditMeta(kind, extra) {
18515
+ return domainMeta("audit", kind, extra);
18516
+ }
18517
+ var DEFAULT_INCLUDE_TYPES = /* @__PURE__ */ new Set([
18518
+ "data",
18519
+ "error",
18520
+ "complete",
18521
+ "teardown"
18522
+ ]);
18523
+ var AuditTrailGraph = class extends Graph {
18524
+ entries;
18525
+ count;
18526
+ _log;
18527
+ _target;
18528
+ constructor(target, opts) {
18529
+ super(opts.name ?? `${target.name}_audit`, opts.graph);
18530
+ this._target = target;
18531
+ this._log = reactiveLog([], {
18532
+ name: "entries",
18533
+ ...opts.maxSize != null ? { maxSize: opts.maxSize } : {}
18534
+ });
18535
+ this.entries = this._log.entries;
18536
+ this.add("entries", this.entries);
18537
+ this.count = derived(
18538
+ [this.entries],
18539
+ ([snapshot]) => snapshot.length,
18540
+ { name: "count", describeKind: "derived", meta: auditMeta("count") }
18541
+ );
18542
+ this.add("count", this.count);
18543
+ this.addDisposer(keepalive(this.count));
18544
+ const includeTypes = opts.includeTypes != null ? new Set(opts.includeTypes) : DEFAULT_INCLUDE_TYPES;
18545
+ const filter2 = opts.filter;
18546
+ let seq = 0;
18547
+ const handle = target.observe({ timeline: true, structured: true });
18548
+ const offEvent = handle.onEvent((event) => {
18549
+ if (event.type === "derived") return;
18550
+ const type = event.type;
18551
+ if (!includeTypes.has(type)) return;
18552
+ const path = event.path ?? "";
18553
+ const entry = {
18554
+ seq: seq++,
18555
+ timestamp_ns: event.timestamp_ns ?? monotonicNs(),
18556
+ wall_clock_ns: wallClockNs(),
18557
+ path,
18558
+ type
18559
+ };
18560
+ const node2 = path ? safeNode(target, path) : void 0;
18561
+ const lastMutation = node2?.lastMutation;
18562
+ if (lastMutation != null) entry.actor = lastMutation.actor;
18563
+ if (type === "data") entry.value = event.data;
18564
+ if (type === "error") entry.error = event.data;
18565
+ const reason = path ? safeAnnotation(target, path) : void 0;
18566
+ if (reason != null) entry.reason = reason;
18567
+ if (filter2 != null && !filter2(entry)) return;
18568
+ this._log.append(entry);
18569
+ });
18570
+ this.addDisposer(() => {
18571
+ offEvent();
18572
+ handle.dispose();
18573
+ });
18574
+ this.addDisposer(() => this._log.disposeAllViews());
18575
+ }
18576
+ /** All entries currently in the ring (snapshot). */
18577
+ all() {
18578
+ return this.entries.cache ?? [];
18579
+ }
18580
+ /** Entries matching `path`. Order preserved. */
18581
+ byNode(path) {
18582
+ return this.all().filter((e) => e.path === path);
18583
+ }
18584
+ /** Entries whose `actor.id` matches. Use `byActorType` for type filtering. */
18585
+ byActor(actorId) {
18586
+ return this.all().filter((e) => e.actor?.id === actorId);
18587
+ }
18588
+ /** Entries whose `actor.type` matches (e.g. `"llm"`, `"human"`). */
18589
+ byActorType(type) {
18590
+ return this.all().filter((e) => e.actor?.type === type);
18591
+ }
18592
+ /**
18593
+ * Entries with `timestamp_ns` in `[start_ns, end_ns)` (end exclusive).
18594
+ * Omit `end_ns` to query open-ended.
18595
+ */
18596
+ byTimeRange(start_ns, end_ns) {
18597
+ return this.all().filter((e) => {
18598
+ if (e.timestamp_ns < start_ns) return false;
18599
+ if (end_ns != null && e.timestamp_ns >= end_ns) return false;
17970
18600
  return true;
18601
+ });
18602
+ }
18603
+ /** Reference to the audited graph (escape hatch for tooling). */
18604
+ get target() {
18605
+ return this._target;
18606
+ }
18607
+ };
18608
+ function auditTrail(target, opts = {}) {
18609
+ return new AuditTrailGraph(target, opts);
18610
+ }
18611
+ var PolicyEnforcerGraph = class extends Graph {
18612
+ policies;
18613
+ violations;
18614
+ violationCount;
18615
+ _target;
18616
+ _mode;
18617
+ _currentGuard;
18618
+ constructor(target, policies, opts) {
18619
+ super(opts.name ?? `${target.name}_policy`, opts.graph);
18620
+ this._target = target;
18621
+ this._mode = opts.mode ?? "audit";
18622
+ const policiesNode = isNode3(policies) ? policies : state(policies, { name: "policies" });
18623
+ this.policies = policiesNode;
18624
+ this.add("policies", this.policies);
18625
+ this.violations = new TopicGraph("violations", {
18626
+ retainedLimit: opts.violationsLimit ?? 1e3
18627
+ });
18628
+ this.mount("violations", this.violations);
18629
+ this.violationCount = derived(
18630
+ [this.violations.events],
18631
+ ([snapshot]) => snapshot.length,
18632
+ {
18633
+ name: "violationCount",
18634
+ describeKind: "derived",
18635
+ meta: auditMeta("policy_violation_count")
18636
+ }
18637
+ );
18638
+ this.add("violationCount", this.violationCount);
18639
+ this.addDisposer(keepalive(this.violationCount));
18640
+ const initialRules = policiesNode.cache ?? [];
18641
+ let latestRules = initialRules;
18642
+ this._currentGuard = policyFromRules(latestRules);
18643
+ const offPolicies = policiesNode.subscribe((msgs) => {
18644
+ for (const m of msgs) {
18645
+ if (m[0] === DATA) {
18646
+ latestRules = m[1] ?? [];
18647
+ this._currentGuard = policyFromRules(latestRules);
18648
+ }
18649
+ }
18650
+ });
18651
+ this.addDisposer(offPolicies);
18652
+ const paths = opts.paths != null ? [...opts.paths] : collectPaths(target);
18653
+ if (this._mode === "enforce") {
18654
+ const restorers = /* @__PURE__ */ new Map();
18655
+ const wrapAndPush = (path) => {
18656
+ if (restorers.has(path)) return;
18657
+ const node2 = safeNode(target, path);
18658
+ if (!(node2 instanceof NodeImpl)) return;
18659
+ const pathGuard = (actor, action2) => {
18660
+ const ok = this._currentGuard(actor, action2);
18661
+ if (!ok) {
18662
+ this._publishViolation(actor, action2, path, "blocked");
18663
+ }
18664
+ return ok;
18665
+ };
18666
+ restorers.set(path, node2._pushGuard(pathGuard));
18667
+ };
18668
+ for (const path of paths) wrapAndPush(path);
18669
+ if (opts.paths == null) {
18670
+ const offTopology = watchTopologyTree(target, (event, emitter, prefix) => {
18671
+ if (event.kind === "added") {
18672
+ if (event.nodeKind === "node") {
18673
+ wrapAndPush(`${prefix}${event.name}`);
18674
+ } else {
18675
+ const child = emitter._mounts.get(event.name);
18676
+ if (!(child instanceof Graph)) return;
18677
+ const mountPrefix = `${prefix}${event.name}::`;
18678
+ const localPaths = collectPaths(child);
18679
+ for (const localPath of localPaths) {
18680
+ wrapAndPush(
18681
+ localPath === "" ? `${prefix}${event.name}` : `${mountPrefix}${localPath}`
18682
+ );
18683
+ }
18684
+ }
18685
+ } else if (event.kind === "removed") {
18686
+ if (event.nodeKind === "node") {
18687
+ const qp = `${prefix}${event.name}`;
18688
+ const r = restorers.get(qp);
18689
+ if (r != null) {
18690
+ r();
18691
+ restorers.delete(qp);
18692
+ }
18693
+ } else {
18694
+ const mountQp = `${prefix}${event.name}`;
18695
+ const mountPrefix = `${mountQp}::`;
18696
+ for (const [p, r] of restorers) {
18697
+ if (p === mountQp || p.startsWith(mountPrefix)) {
18698
+ r();
18699
+ restorers.delete(p);
18700
+ }
18701
+ }
18702
+ }
18703
+ }
18704
+ });
18705
+ this.addDisposer(offTopology);
18706
+ } else {
18707
+ const offCleanup = target.topology.subscribe((msgs) => {
18708
+ for (const m of msgs) {
18709
+ if (m[0] !== DATA) continue;
18710
+ const event = m[1];
18711
+ if (event.kind !== "removed" || event.nodeKind !== "node") continue;
18712
+ const r = restorers.get(event.name);
18713
+ if (r != null) {
18714
+ r();
18715
+ restorers.delete(event.name);
18716
+ }
18717
+ }
18718
+ });
18719
+ this.addDisposer(offCleanup);
18720
+ }
18721
+ this.addDisposer(() => {
18722
+ for (const r of restorers.values()) r();
18723
+ restorers.clear();
18724
+ });
18725
+ } else {
18726
+ const handle = target.observe({ timeline: true, structured: true });
18727
+ const off = handle.onEvent((event) => {
18728
+ if (event.type !== "data" && event.type !== "error") return;
18729
+ const path = event.path ?? "";
18730
+ if (!path) return;
18731
+ if (opts.paths != null && !opts.paths.includes(path)) return;
18732
+ const node2 = safeNode(target, path);
18733
+ const lastMutation = node2?.lastMutation;
18734
+ if (lastMutation == null) return;
18735
+ const action2 = "write";
18736
+ if (this._currentGuard(lastMutation.actor, action2)) return;
18737
+ this._publishViolation(lastMutation.actor, action2, path, "observed");
18738
+ });
18739
+ this.addDisposer(() => {
18740
+ off();
18741
+ handle.dispose();
18742
+ });
17971
18743
  }
17972
18744
  }
17973
- return false;
18745
+ _publishViolation(actor, action2, path, result) {
18746
+ this.violations.publish({
18747
+ timestamp_ns: monotonicNs(),
18748
+ wall_clock_ns: wallClockNs(),
18749
+ path,
18750
+ actor,
18751
+ action: action2,
18752
+ mode: this._mode,
18753
+ result
18754
+ });
18755
+ }
18756
+ /** Snapshot of recorded violations. */
18757
+ all() {
18758
+ return this.violations.retained();
18759
+ }
18760
+ get mode() {
18761
+ return this._mode;
18762
+ }
18763
+ get target() {
18764
+ return this._target;
18765
+ }
18766
+ };
18767
+ function policyEnforcer(target, policies, opts = {}) {
18768
+ return new PolicyEnforcerGraph(target, policies, opts);
18769
+ }
18770
+ function reactiveExplainPath(target, from, to, opts) {
18771
+ let v = 0;
18772
+ const version2 = state(v, { name: "explain_version" });
18773
+ const handle = target.observe({ timeline: true, structured: true });
18774
+ const off = handle.onEvent((event) => {
18775
+ const t = event.type;
18776
+ if (t !== "data" && t !== "error" && t !== "complete" && t !== "teardown") return;
18777
+ v += 1;
18778
+ version2.emit(v);
18779
+ });
18780
+ const explainOpts = {
18781
+ ...opts?.maxDepth != null ? { maxDepth: opts.maxDepth } : {},
18782
+ ...opts?.findCycle === true ? { findCycle: true } : {}
18783
+ };
18784
+ const node2 = derived([version2], () => target.explain(from, to, explainOpts), {
18785
+ name: opts?.name ?? "explain",
18786
+ describeKind: "derived",
18787
+ equals: (a, b) => a.found === b.found && a.reason === b.reason && a.steps.length === b.steps.length && causalStepsEqual(a.steps, b.steps),
18788
+ meta: auditMeta("explain_path", { from, to })
18789
+ });
18790
+ const stopKeepalive = keepalive(node2);
18791
+ return {
18792
+ node: node2,
18793
+ dispose() {
18794
+ off();
18795
+ handle.dispose();
18796
+ stopKeepalive();
18797
+ }
18798
+ };
17974
18799
  }
17975
- var kinsokuStart = /* @__PURE__ */ new Set([
17976
- "\uFF0C",
17977
- "\uFF0E",
17978
- "\uFF01",
17979
- "\uFF1A",
17980
- "\uFF1B",
17981
- "\uFF1F",
17982
- "\u3001",
17983
- "\u3002",
17984
- "\u30FB",
17985
- "\uFF09",
17986
- "\u3015",
17987
- "\u3009",
17988
- "\u300B",
17989
- "\u300D",
17990
- "\u300F",
18800
+ function causalStepsEqual(a, b) {
18801
+ for (let i = 0; i < a.length; i++) {
18802
+ const x = a[i];
18803
+ const y = b[i];
18804
+ if (x.path !== y.path) return false;
18805
+ if (x.type !== y.type) return false;
18806
+ if (x.status !== y.status) return false;
18807
+ if (x.hop !== y.hop) return false;
18808
+ if (x.dep_index !== y.dep_index) return false;
18809
+ if (x.reason !== y.reason) return false;
18810
+ if (x.value !== y.value) return false;
18811
+ if (x.lastMutation !== y.lastMutation) return false;
18812
+ const xv = x.v;
18813
+ const yv = y.v;
18814
+ if (xv !== yv) {
18815
+ if (xv == null || yv == null) return false;
18816
+ if (xv.id !== yv.id || xv.version !== yv.version) return false;
18817
+ }
18818
+ }
18819
+ return true;
18820
+ }
18821
+ function complianceSnapshot(target, opts = {}) {
18822
+ const result = {
18823
+ format_version: 1,
18824
+ timestamp_ns: monotonicNs(),
18825
+ wall_clock_ns: wallClockNs(),
18826
+ graph: target.snapshot()
18827
+ };
18828
+ if (opts.actor != null) result.actor = opts.actor;
18829
+ if (opts.audit != null) {
18830
+ const entries = [...opts.audit.all()];
18831
+ result.audit = { count: entries.length, entries };
18832
+ }
18833
+ if (opts.policies != null) {
18834
+ const rules = opts.policies.policies.cache ?? [];
18835
+ result.policies = {
18836
+ mode: opts.policies.mode,
18837
+ rules,
18838
+ violations: [...opts.policies.all()]
18839
+ };
18840
+ }
18841
+ const fingerprint = computeFingerprint(result);
18842
+ return { ...result, fingerprint };
18843
+ }
18844
+ function isNode3(x) {
18845
+ return typeof x === "object" && x !== null && "subscribe" in x;
18846
+ }
18847
+ function safeNode(target, path) {
18848
+ try {
18849
+ return target.node(path);
18850
+ } catch {
18851
+ return void 0;
18852
+ }
18853
+ }
18854
+ function safeAnnotation(target, path) {
18855
+ try {
18856
+ return target.annotation(path);
18857
+ } catch {
18858
+ return void 0;
18859
+ }
18860
+ }
18861
+ function collectPaths(target) {
18862
+ const described = target.describe({ detail: "minimal" });
18863
+ return Object.keys(described.nodes);
18864
+ }
18865
+ function computeFingerprint(value) {
18866
+ return defaultHash(JSON.stringify(canonicalize(value)));
18867
+ }
18868
+ function canonicalize(value) {
18869
+ const stack = /* @__PURE__ */ new Set();
18870
+ const walk = (v) => {
18871
+ if (v === void 0) return { __undefined: true };
18872
+ if (v === null) return null;
18873
+ const t = typeof v;
18874
+ if (t === "bigint") return { __bigint: v.toString() };
18875
+ if (t !== "object") return v;
18876
+ const obj = v;
18877
+ if (stack.has(obj)) return { __circular: true };
18878
+ stack.add(obj);
18879
+ try {
18880
+ if (Array.isArray(obj)) {
18881
+ return obj.map(walk);
18882
+ }
18883
+ if (obj instanceof Date) {
18884
+ return { __date: obj.toISOString() };
18885
+ }
18886
+ if (obj instanceof RegExp) {
18887
+ return { __regexp: { source: obj.source, flags: obj.flags } };
18888
+ }
18889
+ if (obj instanceof Map) {
18890
+ const entries = [...obj.entries()].map(([k, mv]) => [
18891
+ walk(k),
18892
+ walk(mv)
18893
+ ]);
18894
+ return { __map: entries };
18895
+ }
18896
+ if (obj instanceof Set) {
18897
+ const items = [...obj].map(walk);
18898
+ return { __set: items };
18899
+ }
18900
+ if (ArrayBuffer.isView(obj)) {
18901
+ const ta = obj;
18902
+ const arr = new Array(ta.length);
18903
+ for (let i = 0; i < ta.length; i++) arr[i] = ta[i] ?? 0;
18904
+ return { __typed_array: { ctor: obj.constructor.name, data: arr } };
18905
+ }
18906
+ const out = {};
18907
+ for (const k of Object.keys(obj).sort()) {
18908
+ out[k] = walk(obj[k]);
18909
+ }
18910
+ return out;
18911
+ } finally {
18912
+ stack.delete(obj);
18913
+ }
18914
+ };
18915
+ return walk(value);
18916
+ }
18917
+
18918
+ // src/patterns/demo-shell.ts
18919
+ var demo_shell_exports = {};
18920
+ __export(demo_shell_exports, {
18921
+ demoShell: () => demoShell
18922
+ });
18923
+
18924
+ // src/patterns/reactive-layout/reactive-layout.ts
18925
+ function isCJK(s) {
18926
+ for (const ch of s) {
18927
+ const c = ch.codePointAt(0);
18928
+ if (c >= 19968 && c <= 40959 || // CJK Unified Ideographs
18929
+ c >= 13312 && c <= 19903 || // CJK Extension A
18930
+ c >= 12288 && c <= 12351 || // CJK Symbols and Punctuation
18931
+ c >= 12352 && c <= 12447 || // Hiragana
18932
+ c >= 12448 && c <= 12543 || // Katakana
18933
+ c >= 44032 && c <= 55215 || // Hangul
18934
+ c >= 65280 && c <= 65519) {
18935
+ return true;
18936
+ }
18937
+ }
18938
+ return false;
18939
+ }
18940
+ var kinsokuStart = /* @__PURE__ */ new Set([
18941
+ "\uFF0C",
18942
+ "\uFF0E",
18943
+ "\uFF01",
18944
+ "\uFF1A",
18945
+ "\uFF1B",
18946
+ "\uFF1F",
18947
+ "\u3001",
18948
+ "\u3002",
18949
+ "\u30FB",
18950
+ "\uFF09",
18951
+ "\u3015",
18952
+ "\u3009",
18953
+ "\u300B",
18954
+ "\u300D",
18955
+ "\u300F",
17991
18956
  "\u3011"
17992
18957
  ]);
17993
18958
  var leftStickyPunctuation = /* @__PURE__ */ new Set([
@@ -18054,7 +19019,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
18054
19019
  const normalized = normalizeWhitespace(text);
18055
19020
  if (normalized.length === 0) return [];
18056
19021
  const pieces = segmentText(normalized);
18057
- const graphemeSegmenter = new Intl.Segmenter(void 0, {
19022
+ const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
18058
19023
  granularity: "grapheme"
18059
19024
  });
18060
19025
  const rawTexts = [];
@@ -18098,7 +19063,8 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
18098
19063
  let w = fontCache.get(seg);
18099
19064
  if (w === void 0) {
18100
19065
  if (stats) stats.misses += 1;
18101
- w = adapter.measureSegment(seg, font).width;
19066
+ const raw = adapter.measureSegment(seg, font).width;
19067
+ w = Number.isFinite(raw) && raw >= 0 ? raw : 0;
18102
19068
  fontCache.set(seg, w);
18103
19069
  } else if (stats) {
18104
19070
  stats.hits += 1;
@@ -18120,7 +19086,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
18120
19086
  }
18121
19087
  if (isCJK(t)) {
18122
19088
  let unitText = "";
18123
- for (const gs of graphemeSegmenter.segment(t)) {
19089
+ for (const gs of graphemeSegmenter2.segment(t)) {
18124
19090
  const grapheme = gs.segment;
18125
19091
  if (unitText.length > 0 && kinsokuStart.has(grapheme)) {
18126
19092
  unitText += grapheme;
@@ -18152,7 +19118,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
18152
19118
  let graphemeWidths = null;
18153
19119
  if (mergedWordLike[i] && t.length > 1) {
18154
19120
  const gWidths = [];
18155
- for (const gs of graphemeSegmenter.segment(t)) {
19121
+ for (const gs of graphemeSegmenter2.segment(t)) {
18156
19122
  gWidths.push(measureCached(gs.segment));
18157
19123
  }
18158
19124
  if (gWidths.length > 1) {
@@ -18192,10 +19158,10 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18192
19158
  const seg = segments[i];
18193
19159
  if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
18194
19160
  if (i === lineStartSeg && lineStartGrapheme > 0 && seg.graphemeWidths) {
18195
- const graphemeSegmenter = new Intl.Segmenter(void 0, {
19161
+ const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
18196
19162
  granularity: "grapheme"
18197
19163
  });
18198
- const graphemes = [...graphemeSegmenter.segment(seg.text)].map((g) => g.segment);
19164
+ const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
18199
19165
  text += graphemes.slice(lineStartGrapheme).join("");
18200
19166
  } else {
18201
19167
  text += seg.text;
@@ -18203,10 +19169,10 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18203
19169
  }
18204
19170
  if (endGrapheme > 0 && endSeg < segments.length) {
18205
19171
  const seg = segments[endSeg];
18206
- const graphemeSegmenter = new Intl.Segmenter(void 0, {
19172
+ const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
18207
19173
  granularity: "grapheme"
18208
19174
  });
18209
- const graphemes = [...graphemeSegmenter.segment(seg.text)].map((g) => g.segment);
19175
+ const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
18210
19176
  const startG = lineStartSeg === endSeg ? lineStartGrapheme : 0;
18211
19177
  text += graphemes.slice(startG, endGrapheme).join("");
18212
19178
  }
@@ -18226,7 +19192,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18226
19192
  pendingBreakSeg = -1;
18227
19193
  pendingBreakWidth = 0;
18228
19194
  }
18229
- function canBreakAfter(kind) {
19195
+ function canBreakAfter2(kind) {
18230
19196
  return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
18231
19197
  }
18232
19198
  function startLine(segIdx, graphemeIdx, width) {
@@ -18271,7 +19237,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18271
19237
  } else {
18272
19238
  startLine(i, 0, w);
18273
19239
  }
18274
- if (canBreakAfter(seg.kind)) {
19240
+ if (canBreakAfter2(seg.kind)) {
18275
19241
  pendingBreakSeg = i + 1;
18276
19242
  pendingBreakWidth = seg.kind === "space" ? lineW - w : lineW;
18277
19243
  }
@@ -18279,7 +19245,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18279
19245
  }
18280
19246
  const newW = lineW + w;
18281
19247
  if (newW > maxWidth + 5e-3) {
18282
- if (canBreakAfter(seg.kind)) {
19248
+ if (canBreakAfter2(seg.kind)) {
18283
19249
  lineW += w;
18284
19250
  lineEndSeg = i + 1;
18285
19251
  lineEndGrapheme = 0;
@@ -18303,7 +19269,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18303
19269
  lineW = newW;
18304
19270
  lineEndSeg = i + 1;
18305
19271
  lineEndGrapheme = 0;
18306
- if (canBreakAfter(seg.kind)) {
19272
+ if (canBreakAfter2(seg.kind)) {
18307
19273
  pendingBreakSeg = i + 1;
18308
19274
  pendingBreakWidth = seg.kind === "space" ? lineW - w : lineW;
18309
19275
  }
@@ -18334,9 +19300,289 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
18334
19300
  }
18335
19301
  }
18336
19302
  }
19303
+ function canBreakAfter(kind) {
19304
+ return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
19305
+ }
19306
+ var _graphemeSegmenter = null;
19307
+ function graphemeSegmenter() {
19308
+ if (_graphemeSegmenter === null) {
19309
+ _graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
19310
+ }
19311
+ return _graphemeSegmenter;
19312
+ }
19313
+ function sliceSegmentText(seg, startG, endG) {
19314
+ if (startG === 0 && endG < 0) return seg.text;
19315
+ const graphemes = [...graphemeSegmenter().segment(seg.text)].map((g) => g.segment);
19316
+ const stop = endG < 0 ? graphemes.length : endG;
19317
+ return graphemes.slice(startG, stop).join("");
19318
+ }
19319
+ function buildLineText(segments, startSeg, startG, endSeg, endG, appendHyphen) {
19320
+ let text = "";
19321
+ for (let i = startSeg; i < endSeg; i++) {
19322
+ const seg = segments[i];
19323
+ if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
19324
+ if (i === startSeg && startG > 0) {
19325
+ text += sliceSegmentText(seg, startG, -1);
19326
+ } else {
19327
+ text += seg.text;
19328
+ }
19329
+ }
19330
+ if (endG > 0 && endSeg < segments.length) {
19331
+ const seg = segments[endSeg];
19332
+ const from = startSeg === endSeg ? startG : 0;
19333
+ text += sliceSegmentText(seg, from, endG);
19334
+ }
19335
+ if (appendHyphen) text += "-";
19336
+ return text;
19337
+ }
19338
+ function resolveHyphenWidth(ctx) {
19339
+ if (!ctx || !ctx.adapter || !ctx.font) return 0;
19340
+ const cache = ctx.cache;
19341
+ if (cache) {
19342
+ let fc = cache.get(ctx.font);
19343
+ if (!fc) {
19344
+ fc = /* @__PURE__ */ new Map();
19345
+ cache.set(ctx.font, fc);
19346
+ }
19347
+ let hw = fc.get("-");
19348
+ if (hw === void 0) {
19349
+ hw = ctx.adapter.measureSegment("-", ctx.font).width;
19350
+ fc.set("-", hw);
19351
+ }
19352
+ return hw;
19353
+ }
19354
+ return ctx.adapter.measureSegment("-", ctx.font).width;
19355
+ }
19356
+ function layoutNextLine(segments, cursor, slotWidth, ctx) {
19357
+ let i = cursor.segmentIndex;
19358
+ const initialG = cursor.graphemeIndex;
19359
+ if (i >= segments.length) return null;
19360
+ if (initialG === 0) {
19361
+ while (i < segments.length) {
19362
+ const seg = segments[i];
19363
+ if (seg.kind === "hard-break") {
19364
+ return {
19365
+ text: "",
19366
+ width: 0,
19367
+ start: { segmentIndex: cursor.segmentIndex, graphemeIndex: 0 },
19368
+ end: { segmentIndex: i + 1, graphemeIndex: 0 }
19369
+ };
19370
+ }
19371
+ if (seg.kind === "space" || seg.kind === "zero-width-break" || seg.kind === "soft-hyphen") {
19372
+ i += 1;
19373
+ continue;
19374
+ }
19375
+ break;
19376
+ }
19377
+ if (i >= segments.length) return null;
19378
+ }
19379
+ const hyphenWidth = resolveHyphenWidth(ctx);
19380
+ const startSeg = i;
19381
+ const startG = i === cursor.segmentIndex ? initialG : 0;
19382
+ let lineW = 0;
19383
+ let lineEndSeg = startSeg;
19384
+ let lineEndG = 0;
19385
+ let hasContent = false;
19386
+ let pendingBreakSeg = -1;
19387
+ let pendingBreakG = 0;
19388
+ let pendingBreakWidth = 0;
19389
+ let pendingBreakSoftHyphen = false;
19390
+ const recordPending = (sIdx, gIdx, widthAtBreak, kind) => {
19391
+ pendingBreakSeg = sIdx;
19392
+ pendingBreakG = gIdx;
19393
+ pendingBreakWidth = widthAtBreak;
19394
+ pendingBreakSoftHyphen = kind === "soft-hyphen";
19395
+ };
19396
+ const consumeBreakable = (segIdx, gStart, gWidths) => {
19397
+ for (let g = gStart; g < gWidths.length; g++) {
19398
+ const gw = gWidths[g];
19399
+ if (!hasContent) {
19400
+ lineW = gw;
19401
+ lineEndSeg = segIdx;
19402
+ lineEndG = g + 1;
19403
+ hasContent = true;
19404
+ continue;
19405
+ }
19406
+ if (lineW + gw > slotWidth + 5e-3) {
19407
+ return true;
19408
+ }
19409
+ lineW += gw;
19410
+ lineEndSeg = segIdx;
19411
+ lineEndG = g + 1;
19412
+ }
19413
+ if (lineEndSeg === segIdx && lineEndG === gWidths.length) {
19414
+ lineEndSeg = segIdx + 1;
19415
+ lineEndG = 0;
19416
+ }
19417
+ return false;
19418
+ };
19419
+ if (startG > 0 && startSeg < segments.length) {
19420
+ const seg = segments[startSeg];
19421
+ if (seg.graphemeWidths) {
19422
+ const overflowed = consumeBreakable(startSeg, startG, seg.graphemeWidths);
19423
+ if (overflowed) {
19424
+ const text2 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
19425
+ return {
19426
+ text: text2,
19427
+ width: lineW,
19428
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19429
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19430
+ };
19431
+ }
19432
+ i = lineEndSeg;
19433
+ } else {
19434
+ }
19435
+ }
19436
+ for (; i < segments.length; ) {
19437
+ const seg = segments[i];
19438
+ if (seg.kind === "hard-break") {
19439
+ if (hasContent) {
19440
+ const endsAtSoftHyphen2 = lineEndSeg > 0 && segments[lineEndSeg - 1]?.kind === "soft-hyphen";
19441
+ const text2 = buildLineText(
19442
+ segments,
19443
+ startSeg,
19444
+ startG,
19445
+ lineEndSeg,
19446
+ lineEndG,
19447
+ endsAtSoftHyphen2
19448
+ );
19449
+ return {
19450
+ text: text2,
19451
+ width: lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0),
19452
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19453
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19454
+ };
19455
+ }
19456
+ return {
19457
+ text: "",
19458
+ width: 0,
19459
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19460
+ end: { segmentIndex: i + 1, graphemeIndex: 0 }
19461
+ };
19462
+ }
19463
+ const w = seg.width;
19464
+ if (!hasContent) {
19465
+ if (w > slotWidth && seg.graphemeWidths) {
19466
+ const overflowed = consumeBreakable(i, 0, seg.graphemeWidths);
19467
+ if (overflowed) {
19468
+ const text2 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
19469
+ return {
19470
+ text: text2,
19471
+ width: lineW,
19472
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19473
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19474
+ };
19475
+ }
19476
+ i = lineEndSeg;
19477
+ continue;
19478
+ }
19479
+ lineW = w;
19480
+ lineEndSeg = i + 1;
19481
+ lineEndG = 0;
19482
+ hasContent = true;
19483
+ if (canBreakAfter(seg.kind)) {
19484
+ recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
19485
+ }
19486
+ i += 1;
19487
+ continue;
19488
+ }
19489
+ const newW = lineW + w;
19490
+ if (newW > slotWidth + 5e-3) {
19491
+ if (canBreakAfter(seg.kind)) {
19492
+ lineEndSeg = i + 1;
19493
+ lineEndG = 0;
19494
+ const endsAtSoftHyphen2 = seg.kind === "soft-hyphen";
19495
+ const finalWidth = seg.kind === "space" ? lineW : lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0);
19496
+ const text3 = buildLineText(
19497
+ segments,
19498
+ startSeg,
19499
+ startG,
19500
+ lineEndSeg,
19501
+ lineEndG,
19502
+ endsAtSoftHyphen2
19503
+ );
19504
+ return {
19505
+ text: text3,
19506
+ width: finalWidth,
19507
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19508
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19509
+ };
19510
+ }
19511
+ if (pendingBreakSeg >= 0) {
19512
+ const text3 = buildLineText(
19513
+ segments,
19514
+ startSeg,
19515
+ startG,
19516
+ pendingBreakSeg,
19517
+ pendingBreakG,
19518
+ pendingBreakSoftHyphen
19519
+ );
19520
+ return {
19521
+ text: text3,
19522
+ width: pendingBreakWidth + (pendingBreakSoftHyphen ? hyphenWidth : 0),
19523
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19524
+ end: { segmentIndex: pendingBreakSeg, graphemeIndex: pendingBreakG }
19525
+ };
19526
+ }
19527
+ if (w > slotWidth && seg.graphemeWidths) {
19528
+ const text3 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
19529
+ return {
19530
+ text: text3,
19531
+ width: lineW,
19532
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19533
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19534
+ };
19535
+ }
19536
+ const text2 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
19537
+ return {
19538
+ text: text2,
19539
+ width: lineW,
19540
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19541
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19542
+ };
19543
+ }
19544
+ lineW = newW;
19545
+ lineEndSeg = i + 1;
19546
+ lineEndG = 0;
19547
+ if (canBreakAfter(seg.kind)) {
19548
+ recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
19549
+ }
19550
+ i += 1;
19551
+ }
19552
+ if (!hasContent) return null;
19553
+ const endsAtSoftHyphen = lineEndSeg > 0 && segments[lineEndSeg - 1]?.kind === "soft-hyphen";
19554
+ const text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, endsAtSoftHyphen);
19555
+ return {
19556
+ text,
19557
+ width: lineW + (endsAtSoftHyphen ? hyphenWidth : 0),
19558
+ start: { segmentIndex: startSeg, graphemeIndex: startG },
19559
+ end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
19560
+ };
19561
+ }
19562
+ function carveTextLineSlots(base, blocked, minSlotWidth = 0) {
19563
+ let slots = [base];
19564
+ for (let bi = 0; bi < blocked.length; bi++) {
19565
+ const block = blocked[bi];
19566
+ const next = [];
19567
+ for (let si = 0; si < slots.length; si++) {
19568
+ const slot = slots[si];
19569
+ if (block.right <= slot.left || block.left >= slot.right) {
19570
+ next.push(slot);
19571
+ continue;
19572
+ }
19573
+ if (block.left > slot.left) next.push({ left: slot.left, right: block.left });
19574
+ if (block.right < slot.right) next.push({ left: block.right, right: slot.right });
19575
+ }
19576
+ slots = next;
19577
+ }
19578
+ if (minSlotWidth > 0) {
19579
+ return slots.filter((s) => s.right - s.left >= minSlotWidth);
19580
+ }
19581
+ return slots;
19582
+ }
18337
19583
  function computeCharPositions(lineBreaks, segments, lineHeight) {
18338
19584
  const positions = [];
18339
- const graphemeSegmenter = new Intl.Segmenter(void 0, {
19585
+ const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
18340
19586
  granularity: "grapheme"
18341
19587
  });
18342
19588
  for (let lineIdx = 0; lineIdx < lineBreaks.lines.length; lineIdx++) {
@@ -18349,7 +19595,7 @@ function computeCharPositions(lineBreaks, segments, lineHeight) {
18349
19595
  if (si >= line.endSegment && line.endGrapheme === 0) break;
18350
19596
  continue;
18351
19597
  }
18352
- const graphemes = [...graphemeSegmenter.segment(seg.text)].map((g) => g.segment);
19598
+ const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
18353
19599
  if (graphemes.length === 0) continue;
18354
19600
  const startG = si === line.startSegment ? line.startGrapheme : 0;
18355
19601
  let endG;
@@ -20649,6 +21895,65 @@ ${validation.errors.join("\n")}`);
20649
21895
  return parsed;
20650
21896
  }
20651
21897
 
21898
+ // src/patterns/guarded-execution.ts
21899
+ var guarded_execution_exports = {};
21900
+ __export(guarded_execution_exports, {
21901
+ GuardedExecutionGraph: () => GuardedExecutionGraph,
21902
+ guardedExecution: () => guardedExecution
21903
+ });
21904
+ var GuardedExecutionGraph = class extends Graph {
21905
+ enforcer;
21906
+ violations;
21907
+ _target;
21908
+ _defaultActor;
21909
+ constructor(target, opts) {
21910
+ super(opts.name ?? `${target.name}_guarded`, opts.graph);
21911
+ this._target = target;
21912
+ this._defaultActor = opts.actor;
21913
+ const enforcerOpts = {
21914
+ mode: opts.mode ?? "enforce",
21915
+ name: "enforcer"
21916
+ };
21917
+ if (opts.violationsLimit != null) enforcerOpts.violationsLimit = opts.violationsLimit;
21918
+ this.enforcer = policyEnforcer(target, opts.policies, enforcerOpts);
21919
+ this.violations = this.enforcer.violations;
21920
+ this.mount("enforcer", this.enforcer);
21921
+ }
21922
+ /**
21923
+ * Describe the **target** graph scoped to the configured actor. Returns
21924
+ * only nodes the actor is permitted to see (via the target's node guards
21925
+ * filtering `describe()` via `actor`).
21926
+ *
21927
+ * Pass `{actor}` in opts to override the configured actor for this call.
21928
+ * Pass any standard {@link GraphDescribeOptions} fields (`detail`,
21929
+ * `fields`, `filter`) — they apply to the target's describe.
21930
+ *
21931
+ * **Mode interaction:**
21932
+ * - In `mode: "enforce"` (default), the enforcer stacks a policy-derived
21933
+ * guard on every target node. `scopedDescribe({actor})` then filters by
21934
+ * the AND of per-node guards AND the stacked policy guard.
21935
+ * - In `mode: "audit"`, NO guards are stacked — `scopedDescribe` filters
21936
+ * purely by the target's pre-existing per-node guards. If a target has
21937
+ * no node-level guards, the policy rules you pass have no effect on
21938
+ * visibility (they only populate the `violations` topic on writes).
21939
+ */
21940
+ scopedDescribe(opts) {
21941
+ const actor = opts?.actor ?? this._defaultActor;
21942
+ const describeOpts = {
21943
+ ...opts,
21944
+ ...actor != null ? { actor } : {}
21945
+ };
21946
+ return this._target.describe(describeOpts);
21947
+ }
21948
+ /** The wrapped graph (escape hatch for tooling). */
21949
+ get target() {
21950
+ return this._target;
21951
+ }
21952
+ };
21953
+ function guardedExecution(target, opts) {
21954
+ return new GuardedExecutionGraph(target, opts);
21955
+ }
21956
+
20652
21957
  // src/patterns/harness/index.ts
20653
21958
  var harness_exports = {};
20654
21959
  __export(harness_exports, {
@@ -21330,6 +22635,257 @@ function truncate(s, max) {
21330
22635
  return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
21331
22636
  }
21332
22637
 
22638
+ // src/patterns/lens.ts
22639
+ var lens_exports = {};
22640
+ __export(lens_exports, {
22641
+ LensGraph: () => LensGraph,
22642
+ graphLens: () => graphLens,
22643
+ watchTopologyTree: () => watchTopologyTree
22644
+ });
22645
+ function lensMeta(kind) {
22646
+ return domainMeta("lens", kind);
22647
+ }
22648
+ function computeTopologyStats(described) {
22649
+ const paths = Object.keys(described.nodes);
22650
+ const depsByPath = /* @__PURE__ */ new Map();
22651
+ const dependents = /* @__PURE__ */ new Map();
22652
+ for (const path of paths) {
22653
+ const deps = described.nodes[path]?.deps ?? [];
22654
+ depsByPath.set(path, deps);
22655
+ for (const dep of deps) {
22656
+ if (!dependents.has(dep)) dependents.set(dep, /* @__PURE__ */ new Set());
22657
+ dependents.get(dep).add(path);
22658
+ }
22659
+ }
22660
+ const sources = [];
22661
+ const sinks = [];
22662
+ for (const path of paths) {
22663
+ if ((depsByPath.get(path) ?? []).length === 0) sources.push(path);
22664
+ if (!dependents.has(path)) sinks.push(path);
22665
+ }
22666
+ sources.sort();
22667
+ sinks.sort();
22668
+ const edgeCount = described.edges.length;
22669
+ const WHITE = 0;
22670
+ const GRAY = 1;
22671
+ const BLACK = 2;
22672
+ const color = /* @__PURE__ */ new Map();
22673
+ for (const p of paths) color.set(p, WHITE);
22674
+ let hasCycles = false;
22675
+ const longestFrom = /* @__PURE__ */ new Map();
22676
+ const dfs = (path) => {
22677
+ const c = color.get(path) ?? WHITE;
22678
+ if (c === GRAY) {
22679
+ hasCycles = true;
22680
+ return 0;
22681
+ }
22682
+ if (c === BLACK) return longestFrom.get(path) ?? 0;
22683
+ color.set(path, GRAY);
22684
+ let best = 0;
22685
+ const kids = dependents.get(path);
22686
+ if (kids != null) {
22687
+ for (const k of kids) {
22688
+ const childLongest = dfs(k);
22689
+ if (childLongest + 1 > best) best = childLongest + 1;
22690
+ }
22691
+ }
22692
+ color.set(path, BLACK);
22693
+ longestFrom.set(path, best);
22694
+ return best;
22695
+ };
22696
+ let depth = 0;
22697
+ for (const src of sources) {
22698
+ const d = dfs(src);
22699
+ if (d > depth) depth = d;
22700
+ }
22701
+ for (const p of paths) {
22702
+ if (color.get(p) === WHITE) dfs(p);
22703
+ }
22704
+ return {
22705
+ nodeCount: paths.length,
22706
+ edgeCount,
22707
+ subgraphCount: described.subgraphs.length,
22708
+ sources,
22709
+ sinks,
22710
+ depth,
22711
+ hasCycles
22712
+ };
22713
+ }
22714
+ function computeHealthReport(described) {
22715
+ const problems = [];
22716
+ for (const [path, desc] of Object.entries(described.nodes)) {
22717
+ if (desc.status !== "errored") continue;
22718
+ const entry = { path, status: "errored" };
22719
+ const upstream = reachable(described, path, "upstream", {});
22720
+ for (const p of upstream) {
22721
+ if (p === path) continue;
22722
+ if (described.nodes[p]?.status === "errored") {
22723
+ entry.upstreamCause = p;
22724
+ break;
22725
+ }
22726
+ }
22727
+ problems.push(entry);
22728
+ }
22729
+ problems.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
22730
+ return { ok: problems.length === 0, problems };
22731
+ }
22732
+ function topologyStatsEqual(a, b) {
22733
+ 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);
22734
+ }
22735
+ function healthReportEqual(a, b) {
22736
+ if (a.ok !== b.ok) return false;
22737
+ if (a.problems.length !== b.problems.length) return false;
22738
+ for (let i = 0; i < a.problems.length; i++) {
22739
+ const x = a.problems[i];
22740
+ const y = b.problems[i];
22741
+ if (x.path !== y.path) return false;
22742
+ if (x.status !== y.status) return false;
22743
+ if (x.upstreamCause !== y.upstreamCause) return false;
22744
+ }
22745
+ return true;
22746
+ }
22747
+ function stringArrayEqual(a, b) {
22748
+ if (a.length !== b.length) return false;
22749
+ for (let i = 0; i < a.length; i++) {
22750
+ if (a[i] !== b[i]) return false;
22751
+ }
22752
+ return true;
22753
+ }
22754
+ var LensGraph = class extends Graph {
22755
+ /**
22756
+ * Aggregate structural stats — `nodeCount`, `edgeCount`, `sources`,
22757
+ * `sinks`, `depth`, `hasCycles`, `subgraphCount`. Recomputes on every
22758
+ * structural change via {@link watchTopologyTree} (transitive).
22759
+ *
22760
+ * Named `stats` (not `topology`) because `Graph.topology` already names
22761
+ * the raw `TopologyEvent` stream on every graph including `LensGraph`;
22762
+ * giving the lens its own `topology` accessor with an incompatible
22763
+ * `Node<TopologyStats>` type would break Liskov substitutability.
22764
+ */
22765
+ stats;
22766
+ health;
22767
+ /**
22768
+ * Per-path flow tracker — a live {@link ReactiveMapBundle} keyed by
22769
+ * qualified path. Use `.get(path)` / `.has(path)` / `.size` for O(1)
22770
+ * sync queries; subscribe to `.entries` for a reactive snapshot of the
22771
+ * whole map. Lazy — the snapshot is materialized only while `.entries`
22772
+ * has subscribers.
22773
+ *
22774
+ * Shape intentionally differs from `stats` / `health` (which are plain
22775
+ * `Node<Report>`) because `flow` is a keyed collection, not a single
22776
+ * aggregate value. The map shape exposes cheaper queries than any
22777
+ * snapshot-based design.
22778
+ */
22779
+ flow;
22780
+ _target;
22781
+ constructor(target, opts = {}) {
22782
+ super(opts.name ?? `${target.name}_lens`, opts.graph);
22783
+ this._target = target;
22784
+ let statsVersion = 0;
22785
+ let healthVersion = 0;
22786
+ const statsTick = state(0, { name: "stats_tick" });
22787
+ const healthTick = state(0, { name: "health_tick" });
22788
+ this.add("stats_tick", statsTick);
22789
+ this.add("health_tick", healthTick);
22790
+ const mapOpts = { name: "flow" };
22791
+ if (opts.maxFlowPaths != null) mapOpts.maxSize = opts.maxFlowPaths;
22792
+ this.flow = reactiveMap(mapOpts);
22793
+ this.add("flow", this.flow.entries);
22794
+ const pathFilter = opts.pathFilter;
22795
+ const offTopology = watchTopologyTree(target, (event, _emitter, prefix) => {
22796
+ statsVersion += 1;
22797
+ statsTick.emit(statsVersion);
22798
+ healthVersion += 1;
22799
+ healthTick.emit(healthVersion);
22800
+ if (event.kind === "removed") {
22801
+ if (event.nodeKind === "node") {
22802
+ const qp = `${prefix}${event.name}`;
22803
+ this.flow.delete(qp);
22804
+ } else {
22805
+ const mountPrefix = `${prefix}${event.name}::`;
22806
+ const keysToDelete = [];
22807
+ for (const relativePath of event.audit.nodes) {
22808
+ const qualified = relativePath === "" ? `${prefix}${event.name}` : `${mountPrefix}${relativePath}`;
22809
+ keysToDelete.push(qualified);
22810
+ }
22811
+ if (keysToDelete.length > 0) this.flow.deleteMany(keysToDelete);
22812
+ }
22813
+ }
22814
+ });
22815
+ this.addDisposer(offTopology);
22816
+ const observeHandle = target.observe({ timeline: true, structured: true });
22817
+ const offObserve = observeHandle.onEvent((event) => {
22818
+ const t = event.type;
22819
+ if (t === "error" || t === "complete" || t === "data" || t === "teardown") {
22820
+ healthVersion += 1;
22821
+ healthTick.emit(healthVersion);
22822
+ }
22823
+ if (t === "data") {
22824
+ const path = event.path ?? "";
22825
+ if (!path) return;
22826
+ if (pathFilter != null && !pathFilter(path)) return;
22827
+ const existing = this.flow.get(path);
22828
+ const count = existing != null ? existing.count + 1 : 1;
22829
+ this.flow.set(path, { path, count, lastUpdate_ns: monotonicNs() });
22830
+ }
22831
+ });
22832
+ this.addDisposer(() => {
22833
+ offObserve();
22834
+ observeHandle.dispose();
22835
+ });
22836
+ this.stats = derived(
22837
+ [statsTick],
22838
+ () => computeTopologyStats(target.describe({ detail: "minimal" })),
22839
+ {
22840
+ name: "stats",
22841
+ describeKind: "derived",
22842
+ equals: topologyStatsEqual,
22843
+ meta: lensMeta("stats")
22844
+ }
22845
+ );
22846
+ this.add("stats", this.stats);
22847
+ this.addDisposer(keepalive(this.stats));
22848
+ this.health = derived(
22849
+ [healthTick],
22850
+ () => computeHealthReport(target.describe({ detail: "standard" })),
22851
+ {
22852
+ name: "health",
22853
+ describeKind: "derived",
22854
+ equals: healthReportEqual,
22855
+ meta: lensMeta("health")
22856
+ }
22857
+ );
22858
+ this.add("health", this.health);
22859
+ this.addDisposer(keepalive(this.health));
22860
+ }
22861
+ /**
22862
+ * Live causal chain from `from` to `to`. Recomputes whenever the target
22863
+ * mutates. Disposed automatically when the lens is destroyed.
22864
+ *
22865
+ * **Lifetime note:** every call to `why()` registers a lens-owned disposer
22866
+ * that runs on `lens.destroy()`. The returned `dispose` function releases
22867
+ * the internal subscription but does NOT remove the lens-owned disposer —
22868
+ * so heavy calling (e.g. per render frame) accumulates no-op disposers
22869
+ * until lens teardown. Cache the returned handle for long-lived queries.
22870
+ *
22871
+ * @param from - Qualified path of the upstream endpoint.
22872
+ * @param to - Qualified path of the downstream endpoint.
22873
+ * @param opts - See {@link reactiveExplainPath}.
22874
+ */
22875
+ why(from, to, opts) {
22876
+ const handle = reactiveExplainPath(this._target, from, to, opts);
22877
+ this.addDisposer(handle.dispose);
22878
+ return handle;
22879
+ }
22880
+ /** Reference to the lensed graph. */
22881
+ get target() {
22882
+ return this._target;
22883
+ }
22884
+ };
22885
+ function graphLens(target, opts) {
22886
+ return new LensGraph(target, opts);
22887
+ }
22888
+
21333
22889
  // src/patterns/reactive-layout/index.ts
21334
22890
  var reactive_layout_exports = {};
21335
22891
  __export(reactive_layout_exports, {
@@ -21340,14 +22896,20 @@ __export(reactive_layout_exports, {
21340
22896
  PrecomputedAdapter: () => PrecomputedAdapter,
21341
22897
  SvgBoundsAdapter: () => SvgBoundsAdapter,
21342
22898
  analyzeAndMeasure: () => analyzeAndMeasure,
22899
+ carveTextLineSlots: () => carveTextLineSlots,
22900
+ circleIntervalForBand: () => circleIntervalForBand,
21343
22901
  computeBlockFlow: () => computeBlockFlow,
21344
22902
  computeCharPositions: () => computeCharPositions,
22903
+ computeFlowLines: () => computeFlowLines,
21345
22904
  computeLineBreaks: () => computeLineBreaks,
21346
22905
  computeTotalHeight: () => computeTotalHeight,
22906
+ layoutNextLine: () => layoutNextLine,
21347
22907
  measureBlock: () => measureBlock,
21348
22908
  measureBlocks: () => measureBlocks,
21349
22909
  reactiveBlockLayout: () => reactiveBlockLayout,
21350
- reactiveLayout: () => reactiveLayout
22910
+ reactiveFlowLayout: () => reactiveFlowLayout,
22911
+ reactiveLayout: () => reactiveLayout,
22912
+ rectIntervalForBand: () => rectIntervalForBand
21351
22913
  });
21352
22914
 
21353
22915
  // src/patterns/reactive-layout/measurement-adapters.ts
@@ -21544,7 +23106,7 @@ var CanvasMeasureAdapter = class {
21544
23106
  this.currentFont = font;
21545
23107
  }
21546
23108
  let width = ctx.measureText(text).width;
21547
- if (this.emojiCorrection !== 1 && /\p{Emoji_Presentation}/u.test(text)) {
23109
+ if (this.emojiCorrection !== 1 && new RegExp("\\p{Emoji_Presentation}", "u").test(text)) {
21548
23110
  width *= this.emojiCorrection;
21549
23111
  }
21550
23112
  return { width };
@@ -21815,6 +23377,564 @@ function reactiveBlockLayout(opts) {
21815
23377
  };
21816
23378
  }
21817
23379
 
23380
+ // src/patterns/reactive-layout/reactive-flow-layout.ts
23381
+ function circleIntervalForBand(o, bandTop, bandBottom) {
23382
+ const hPad = o.hPad ?? 0;
23383
+ const vPad = o.vPad ?? 0;
23384
+ const top = bandTop - vPad;
23385
+ const bottom = bandBottom + vPad;
23386
+ if (top >= o.cy + o.r || bottom <= o.cy - o.r) return null;
23387
+ const minDy = o.cy >= top && o.cy <= bottom ? 0 : o.cy < top ? top - o.cy : o.cy - bottom;
23388
+ if (minDy >= o.r) return null;
23389
+ const maxDx = Math.sqrt(o.r * o.r - minDy * minDy);
23390
+ return { left: o.cx - maxDx - hPad, right: o.cx + maxDx + hPad };
23391
+ }
23392
+ function rectIntervalForBand(o, bandTop, bandBottom) {
23393
+ const hPad = o.hPad ?? 0;
23394
+ const vPad = o.vPad ?? 0;
23395
+ if (bandBottom <= o.y - vPad) return null;
23396
+ if (bandTop >= o.y + o.h + vPad) return null;
23397
+ return { left: o.x - hPad, right: o.x + o.w + hPad };
23398
+ }
23399
+ function obstacleIntervalForBand(o, bandTop, bandBottom) {
23400
+ return o.kind === "circle" ? circleIntervalForBand(o, bandTop, bandBottom) : rectIntervalForBand(o, bandTop, bandBottom);
23401
+ }
23402
+ function computeFlowLines(segments, container, columns, obstacles, lineHeight, minSlotWidth) {
23403
+ const lines = [];
23404
+ let cursor = { segmentIndex: 0, graphemeIndex: 0 };
23405
+ if (segments.length === 0 || columns.count <= 0 || lineHeight <= 0) {
23406
+ return { lines, cursor };
23407
+ }
23408
+ const padX = container.paddingX ?? 0;
23409
+ const padY = container.paddingY ?? 0;
23410
+ const availWidth = Math.max(0, container.width - padX * 2);
23411
+ const availHeight = Math.max(0, container.height - padY * 2);
23412
+ const gapTotal = columns.gap * Math.max(0, columns.count - 1);
23413
+ const colWidth = Math.max(0, (availWidth - gapTotal) / columns.count);
23414
+ if (colWidth <= 0) return { lines, cursor };
23415
+ outerCol: for (let col = 0; col < columns.count; col++) {
23416
+ const colLeft = padX + col * (colWidth + columns.gap);
23417
+ const colRight = colLeft + colWidth;
23418
+ let bandTop = padY;
23419
+ while (bandTop + lineHeight <= padY + availHeight) {
23420
+ const bandBottom = bandTop + lineHeight;
23421
+ const blocked = [];
23422
+ for (let oi = 0; oi < obstacles.length; oi++) {
23423
+ const iv = obstacleIntervalForBand(obstacles[oi], bandTop, bandBottom);
23424
+ if (iv !== null) blocked.push(iv);
23425
+ }
23426
+ const slots = carveTextLineSlots({ left: colLeft, right: colRight }, blocked, minSlotWidth);
23427
+ if (slots.length === 0) {
23428
+ bandTop += lineHeight;
23429
+ continue;
23430
+ }
23431
+ let hardBreakThisBand = false;
23432
+ for (let si = 0; si < slots.length; si++) {
23433
+ const slot = slots[si];
23434
+ const slotW = slot.right - slot.left;
23435
+ const line = layoutNextLine(segments, cursor, slotW);
23436
+ if (line === null) {
23437
+ return { lines, cursor };
23438
+ }
23439
+ if (line.text.length === 0 && line.width === 0) {
23440
+ cursor = line.end;
23441
+ hardBreakThisBand = true;
23442
+ break;
23443
+ }
23444
+ lines.push({
23445
+ x: slot.left,
23446
+ y: bandTop,
23447
+ width: line.width,
23448
+ slotWidth: slotW,
23449
+ text: line.text,
23450
+ columnIndex: col,
23451
+ flushToRight: slot.right < colRight - 0.5
23452
+ });
23453
+ cursor = line.end;
23454
+ }
23455
+ bandTop += lineHeight;
23456
+ if (hardBreakThisBand) continue;
23457
+ if (cursor.segmentIndex >= segments.length) break outerCol;
23458
+ }
23459
+ if (cursor.segmentIndex >= segments.length) break;
23460
+ }
23461
+ return { lines, cursor };
23462
+ }
23463
+ function reactiveFlowLayout(opts) {
23464
+ const { adapter, name = "reactive-flow-layout", minSlotWidth = 20 } = opts;
23465
+ const g = new Graph(name);
23466
+ const measureCache = /* @__PURE__ */ new Map();
23467
+ const textNode = state(opts.text ?? "", { name: "text" });
23468
+ const fontNode = state(opts.font ?? "16px sans-serif", { name: "font" });
23469
+ const lineHeightNode = state(opts.lineHeight ?? 20, { name: "line-height" });
23470
+ const containerNode = state(
23471
+ opts.container ?? { width: 800, height: 600, paddingX: 0, paddingY: 0 },
23472
+ { name: "container" }
23473
+ );
23474
+ const columnsNode = state(opts.columns ?? { count: 1, gap: 0 }, {
23475
+ name: "columns"
23476
+ });
23477
+ const obstaclesNode = state(opts.obstacles ?? [], { name: "obstacles" });
23478
+ const segmentsNode = node(
23479
+ [textNode, fontNode],
23480
+ (data, actions, ctx) => {
23481
+ const b0 = data[0];
23482
+ const textVal = b0 != null && b0.length > 0 ? b0.at(-1) : ctx.prevData[0];
23483
+ const b1 = data[1];
23484
+ const fontVal = b1 != null && b1.length > 0 ? b1.at(-1) : ctx.prevData[1];
23485
+ const result = analyzeAndMeasure(textVal, fontVal, adapter, measureCache);
23486
+ actions.emit(result);
23487
+ return () => {
23488
+ measureCache.clear();
23489
+ adapter.clearCache?.();
23490
+ };
23491
+ },
23492
+ { name: "segments", describeKind: "derived" }
23493
+ );
23494
+ const flowLinesNode = derived(
23495
+ [segmentsNode, containerNode, columnsNode, obstaclesNode, lineHeightNode],
23496
+ ([segs, cont, cols, obs, lh]) => {
23497
+ const segments = segs;
23498
+ const t0 = monotonicNs();
23499
+ const { lines: result, cursor } = computeFlowLines(
23500
+ segments,
23501
+ cont,
23502
+ cols,
23503
+ obs,
23504
+ lh,
23505
+ minSlotWidth
23506
+ );
23507
+ const elapsed = monotonicNs() - t0;
23508
+ const overflow = Math.max(0, segments.length - cursor.segmentIndex);
23509
+ const meta = flowLinesNode.meta;
23510
+ if (meta) {
23511
+ emitToMeta(meta["line-count"], result.length);
23512
+ emitToMeta(meta["layout-time-ns"], elapsed);
23513
+ emitToMeta(meta["overflow-segments"], overflow);
23514
+ }
23515
+ return result;
23516
+ },
23517
+ {
23518
+ name: "flow-lines",
23519
+ meta: {
23520
+ "line-count": 0,
23521
+ "layout-time-ns": 0,
23522
+ "overflow-segments": 0
23523
+ },
23524
+ equals: (a, b) => {
23525
+ const la = a;
23526
+ const lb = b;
23527
+ if (la.length !== lb.length) return false;
23528
+ for (let i = 0; i < la.length; i++) {
23529
+ const pa = la[i];
23530
+ const pb = lb[i];
23531
+ if (pa.x !== pb.x || pa.y !== pb.y || pa.width !== pb.width || pa.slotWidth !== pb.slotWidth || pa.text !== pb.text || pa.columnIndex !== pb.columnIndex || pa.flushToRight !== pb.flushToRight)
23532
+ return false;
23533
+ }
23534
+ return true;
23535
+ }
23536
+ }
23537
+ );
23538
+ g.add("text", textNode);
23539
+ g.add("font", fontNode);
23540
+ g.add("line-height", lineHeightNode);
23541
+ g.add("container", containerNode);
23542
+ g.add("columns", columnsNode);
23543
+ g.add("obstacles", obstaclesNode);
23544
+ g.add("segments", segmentsNode);
23545
+ g.add("flow-lines", flowLinesNode);
23546
+ return {
23547
+ graph: g,
23548
+ setText: (t) => g.set("text", t),
23549
+ setFont: (f) => g.set("font", f),
23550
+ setLineHeight: (lh) => g.set("line-height", lh),
23551
+ setContainer: (c) => g.set("container", c),
23552
+ setColumns: (c) => g.set("columns", c),
23553
+ setObstacles: (o) => g.set("obstacles", o),
23554
+ segments: segmentsNode,
23555
+ flowLines: flowLinesNode
23556
+ };
23557
+ }
23558
+
23559
+ // src/patterns/resilient-pipeline.ts
23560
+ var resilient_pipeline_exports = {};
23561
+ __export(resilient_pipeline_exports, {
23562
+ NS_PER_MS: () => NS_PER_MS,
23563
+ NS_PER_SEC: () => NS_PER_SEC,
23564
+ resilientPipeline: () => resilientPipeline
23565
+ });
23566
+ function resilientPipeline(source, opts = {}) {
23567
+ let current = source;
23568
+ if (opts.rateLimit != null) {
23569
+ current = rateLimiter(current, opts.rateLimit);
23570
+ }
23571
+ if (opts.budget != null && opts.budget.length > 0) {
23572
+ current = budgetGate(current, opts.budget);
23573
+ }
23574
+ let breakerState;
23575
+ if (opts.breaker != null) {
23576
+ const breaker = circuitBreaker(opts.breaker);
23577
+ const onOpen = opts.breakerOnOpen ?? "skip";
23578
+ const wrapped = withBreaker(breaker, { onOpen })(current);
23579
+ current = wrapped.node;
23580
+ breakerState = wrapped.breakerState;
23581
+ }
23582
+ if (opts.timeoutMs != null) {
23583
+ if (opts.timeoutMs <= 0) throw new RangeError("timeoutMs must be > 0");
23584
+ if (opts.timeoutMs > 9e6) {
23585
+ throw new RangeError(
23586
+ "timeoutMs must be <= 9_000_000 (\u22482.5h) to stay within safe ns arithmetic"
23587
+ );
23588
+ }
23589
+ current = timeout(current, opts.timeoutMs * NS_PER_MS);
23590
+ }
23591
+ if (opts.retry != null) {
23592
+ current = retry(current, opts.retry);
23593
+ }
23594
+ if (opts.fallback !== void 0) {
23595
+ current = fallback(current, opts.fallback);
23596
+ }
23597
+ const withStatusBundle = withStatus(current, { initialStatus: opts.initialStatus ?? "pending" });
23598
+ return {
23599
+ node: withStatusBundle.node,
23600
+ status: withStatusBundle.status,
23601
+ error: withStatusBundle.error,
23602
+ breakerState
23603
+ };
23604
+ }
23605
+
23606
+ // src/patterns/surface/index.ts
23607
+ var surface_exports = {};
23608
+ __export(surface_exports, {
23609
+ SNAPSHOT_WIRE_VERSION: () => SNAPSHOT_WIRE_VERSION,
23610
+ SurfaceError: () => SurfaceError,
23611
+ asSurfaceError: () => asSurfaceError,
23612
+ createGraph: () => createGraph,
23613
+ deleteSnapshot: () => deleteSnapshot,
23614
+ diffSnapshots: () => diffSnapshots,
23615
+ listSnapshots: () => listSnapshots,
23616
+ restoreSnapshot: () => restoreSnapshot,
23617
+ runReduction: () => runReduction,
23618
+ saveSnapshot: () => saveSnapshot
23619
+ });
23620
+
23621
+ // src/patterns/surface/errors.ts
23622
+ var SurfaceError = class extends Error {
23623
+ code;
23624
+ details;
23625
+ constructor(code, message, details) {
23626
+ super(message);
23627
+ this.name = "SurfaceError";
23628
+ this.code = code;
23629
+ if (details !== void 0) this.details = details;
23630
+ }
23631
+ /**
23632
+ * JSON-safe payload for wire serialization. Defensively validates
23633
+ * `details` — if it can't be round-tripped through `JSON.stringify`
23634
+ * (cyclic refs, `BigInt`, `Error` instance not pre-toJSON'd), the
23635
+ * payload falls back to `{code, message}` only rather than crashing
23636
+ * the MCP/CLI wrapper when it serializes this error onto the wire.
23637
+ */
23638
+ toJSON() {
23639
+ const out = { code: this.code, message: this.message };
23640
+ if (this.details !== void 0) {
23641
+ const safe = safeDetails(this.details);
23642
+ if (safe !== void 0) out.details = safe;
23643
+ }
23644
+ return out;
23645
+ }
23646
+ };
23647
+ function safeDetails(details) {
23648
+ try {
23649
+ return JSON.parse(JSON.stringify(details));
23650
+ } catch {
23651
+ return void 0;
23652
+ }
23653
+ }
23654
+ function asSurfaceError(err, fallbackCode = "internal-error") {
23655
+ if (err instanceof SurfaceError) return err;
23656
+ const message = err instanceof Error ? err.message : String(err);
23657
+ return new SurfaceError(fallbackCode, message);
23658
+ }
23659
+
23660
+ // src/patterns/surface/create.ts
23661
+ function createGraph(spec, opts) {
23662
+ const structural = validateSpec(spec);
23663
+ if (!structural.valid) {
23664
+ throw new SurfaceError(
23665
+ "invalid-spec",
23666
+ `GraphSpec validation failed:
23667
+ ${structural.errors.join("\n")}`,
23668
+ { errors: structural.errors }
23669
+ );
23670
+ }
23671
+ const catalog = opts?.catalog ?? {};
23672
+ const catalogValidation = validateSpecAgainstCatalog(spec, catalog);
23673
+ if (!catalogValidation.valid) {
23674
+ throw new SurfaceError(
23675
+ "catalog-error",
23676
+ `Catalog validation failed:
23677
+ ${catalogValidation.errors.join("\n")}`,
23678
+ { errors: catalogValidation.errors }
23679
+ );
23680
+ }
23681
+ try {
23682
+ return compileSpec(spec, opts);
23683
+ } catch (err) {
23684
+ const message = err instanceof Error ? err.message : String(err);
23685
+ throw new SurfaceError("catalog-error", message);
23686
+ }
23687
+ }
23688
+
23689
+ // src/patterns/surface/reduce.ts
23690
+ var DEFAULT_TIMEOUT_MS2 = 3e4;
23691
+ async function runReduction(spec, input, opts) {
23692
+ const inputPath = opts?.inputPath ?? "input";
23693
+ const outputPath = opts?.outputPath ?? "output";
23694
+ const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
23695
+ const graph = createGraph(spec, { catalog: opts?.catalog });
23696
+ let outputNode;
23697
+ try {
23698
+ outputNode = graph.resolve(outputPath);
23699
+ } catch {
23700
+ graph.destroy();
23701
+ throw new SurfaceError(
23702
+ "node-not-found",
23703
+ `reduce: output path "${outputPath}" is not registered`,
23704
+ { path: outputPath }
23705
+ );
23706
+ }
23707
+ try {
23708
+ graph.resolve(inputPath);
23709
+ } catch {
23710
+ graph.destroy();
23711
+ throw new SurfaceError(
23712
+ "node-not-found",
23713
+ `reduce: input path "${inputPath}" is not registered`,
23714
+ { path: inputPath }
23715
+ );
23716
+ }
23717
+ try {
23718
+ return await new Promise((resolve, reject) => {
23719
+ let primed = false;
23720
+ let settled = false;
23721
+ let timer;
23722
+ let unsub;
23723
+ let shouldUnsub = false;
23724
+ const finish = (action2) => {
23725
+ if (settled) return;
23726
+ settled = true;
23727
+ if (timer !== void 0) clearTimeout(timer);
23728
+ if (unsub !== void 0) {
23729
+ unsub();
23730
+ unsub = void 0;
23731
+ } else {
23732
+ shouldUnsub = true;
23733
+ }
23734
+ action2();
23735
+ };
23736
+ unsub = outputNode.subscribe((msgs) => {
23737
+ for (const m of msgs) {
23738
+ if (settled) return;
23739
+ if (!primed) continue;
23740
+ if (m[0] === DATA) {
23741
+ finish(() => resolve(m[1]));
23742
+ return;
23743
+ }
23744
+ if (m[0] === RESOLVED) {
23745
+ const cached2 = outputNode.cache;
23746
+ finish(() => resolve(cached2));
23747
+ return;
23748
+ }
23749
+ if (m[0] === ERROR) {
23750
+ const payload = m[1];
23751
+ const message = payload instanceof Error ? payload.message : String(payload);
23752
+ const cause = payload instanceof Error ? payload : void 0;
23753
+ finish(
23754
+ () => reject(
23755
+ new SurfaceError(
23756
+ "internal-error",
23757
+ `reduce: output emitted ERROR: ${message}`,
23758
+ cause != null ? { cause } : void 0
23759
+ )
23760
+ )
23761
+ );
23762
+ return;
23763
+ }
23764
+ if (m[0] === COMPLETE) {
23765
+ finish(
23766
+ () => reject(
23767
+ new SurfaceError(
23768
+ "internal-error",
23769
+ `reduce: output COMPLETEd without a post-push DATA`
23770
+ )
23771
+ )
23772
+ );
23773
+ return;
23774
+ }
23775
+ }
23776
+ });
23777
+ if (shouldUnsub) {
23778
+ unsub?.();
23779
+ unsub = void 0;
23780
+ }
23781
+ primed = true;
23782
+ try {
23783
+ graph.set(inputPath, input);
23784
+ } catch (err) {
23785
+ const message = err instanceof Error ? err.message : String(err);
23786
+ const cause = err instanceof Error ? err : void 0;
23787
+ finish(
23788
+ () => reject(
23789
+ new SurfaceError(
23790
+ "internal-error",
23791
+ `reduce: failed to set input on "${inputPath}": ${message}`,
23792
+ cause != null ? { path: inputPath, cause } : { path: inputPath }
23793
+ )
23794
+ )
23795
+ );
23796
+ return;
23797
+ }
23798
+ if (!settled && Number.isFinite(timeoutMs) && timeoutMs > 0) {
23799
+ timer = setTimeout(() => {
23800
+ finish(
23801
+ () => reject(
23802
+ new SurfaceError(
23803
+ "reduce-timeout",
23804
+ `reduce: no output emitted within ${timeoutMs}ms`,
23805
+ { timeoutMs, outputPath }
23806
+ )
23807
+ )
23808
+ );
23809
+ }, timeoutMs);
23810
+ timer.unref?.();
23811
+ }
23812
+ });
23813
+ } finally {
23814
+ graph.destroy();
23815
+ }
23816
+ }
23817
+
23818
+ // src/patterns/surface/snapshot.ts
23819
+ var SNAPSHOT_WIRE_VERSION = SNAPSHOT_VERSION;
23820
+ function unwrapCheckpoint(raw, snapshotId) {
23821
+ if (raw == null || typeof raw !== "object") {
23822
+ throw new SurfaceError("snapshot-not-found", `snapshot "${snapshotId}" not found in tier`, {
23823
+ snapshotId
23824
+ });
23825
+ }
23826
+ const record = raw;
23827
+ if ("mode" in record) {
23828
+ if (record.mode === "full" && "snapshot" in record) {
23829
+ return record.snapshot;
23830
+ }
23831
+ if (record.mode === "diff") {
23832
+ throw new SurfaceError(
23833
+ "restore-failed",
23834
+ `snapshot "${snapshotId}" is a diff record; restore the baseline and replay WAL instead`,
23835
+ { snapshotId, mode: "diff" }
23836
+ );
23837
+ }
23838
+ throw new SurfaceError(
23839
+ "restore-failed",
23840
+ `snapshot "${snapshotId}" has unknown mode "${String(record.mode)}"`,
23841
+ { snapshotId, mode: String(record.mode) }
23842
+ );
23843
+ }
23844
+ if ("nodes" in record && "edges" in record && "subgraphs" in record && "name" in record) {
23845
+ return record;
23846
+ }
23847
+ throw new SurfaceError(
23848
+ "restore-failed",
23849
+ `snapshot "${snapshotId}" payload is not a GraphCheckpointRecord or GraphPersistSnapshot`,
23850
+ { snapshotId }
23851
+ );
23852
+ }
23853
+ async function saveSnapshot(graph, snapshotId, tier) {
23854
+ let snapshot;
23855
+ try {
23856
+ snapshot = graph.snapshot();
23857
+ } catch (err) {
23858
+ const message = err instanceof Error ? err.message : String(err);
23859
+ throw new SurfaceError(
23860
+ "snapshot-failed",
23861
+ `snapshot "${snapshotId}" serialization failed: ${message}`,
23862
+ { snapshotId }
23863
+ );
23864
+ }
23865
+ const record = {
23866
+ mode: "full",
23867
+ seq: 0,
23868
+ timestamp_ns: wallClockNs(),
23869
+ format_version: SNAPSHOT_WIRE_VERSION,
23870
+ snapshot
23871
+ };
23872
+ try {
23873
+ await tier.save(snapshotId, record);
23874
+ } catch (err) {
23875
+ const message = err instanceof Error ? err.message : String(err);
23876
+ throw new SurfaceError("snapshot-failed", `snapshot "${snapshotId}" save failed: ${message}`, {
23877
+ snapshotId
23878
+ });
23879
+ }
23880
+ return { snapshotId, timestamp_ns: record.timestamp_ns };
23881
+ }
23882
+ async function restoreSnapshot(snapshotId, tier, opts) {
23883
+ const raw = await tier.load(snapshotId);
23884
+ const snapshot = unwrapCheckpoint(raw, snapshotId);
23885
+ try {
23886
+ return Graph.fromSnapshot(
23887
+ snapshot,
23888
+ opts?.factories ? { factories: opts.factories } : void 0
23889
+ );
23890
+ } catch (err) {
23891
+ const message = err instanceof Error ? err.message : String(err);
23892
+ throw new SurfaceError(
23893
+ "restore-failed",
23894
+ `snapshot "${snapshotId}" restore failed: ${message}`,
23895
+ {
23896
+ snapshotId
23897
+ }
23898
+ );
23899
+ }
23900
+ }
23901
+ async function diffSnapshots(snapshotIdA, snapshotIdB, tier) {
23902
+ const [rawA, rawB] = await Promise.all([tier.load(snapshotIdA), tier.load(snapshotIdB)]);
23903
+ const snapshotA = unwrapCheckpoint(rawA, snapshotIdA);
23904
+ const snapshotB = unwrapCheckpoint(rawB, snapshotIdB);
23905
+ return Graph.diff(snapshotA, snapshotB);
23906
+ }
23907
+ async function listSnapshots(tier) {
23908
+ if (typeof tier.list !== "function") {
23909
+ throw new SurfaceError(
23910
+ "tier-no-list",
23911
+ "StorageTier does not implement list(); wrap the tier with an enumerator or use a different backend"
23912
+ );
23913
+ }
23914
+ return tier.list();
23915
+ }
23916
+ async function deleteSnapshot(snapshotId, tier) {
23917
+ if (typeof tier.clear !== "function") {
23918
+ throw new SurfaceError(
23919
+ "snapshot-failed",
23920
+ `StorageTier is append-only (no clear()); cannot delete "${snapshotId}"`,
23921
+ { snapshotId }
23922
+ );
23923
+ }
23924
+ try {
23925
+ await tier.clear(snapshotId);
23926
+ } catch (err) {
23927
+ const message = err instanceof Error ? err.message : String(err);
23928
+ throw new SurfaceError(
23929
+ "snapshot-failed",
23930
+ `snapshot "${snapshotId}" delete failed: ${message}`,
23931
+ {
23932
+ snapshotId
23933
+ }
23934
+ );
23935
+ }
23936
+ }
23937
+
21818
23938
  // src/index.ts
21819
23939
  var version = "0.0.0";
21820
23940
  // Annotate the CommonJS export names for ESM import in node:
@@ -21855,15 +23975,20 @@ var version = "0.0.0";
21855
23975
  ResettableTimer,
21856
23976
  SIZEOF_OVERHEAD,
21857
23977
  SIZEOF_SYMBOL,
23978
+ SNAPSHOT_VERSION,
23979
+ SNAPSHOT_WIRE_VERSION,
21858
23980
  START,
21859
23981
  START_MSG,
23982
+ SurfaceError,
21860
23983
  TEARDOWN,
21861
23984
  TEARDOWN_MSG,
21862
23985
  TEARDOWN_ONLY_BATCH,
21863
23986
  TimeoutError,
21864
23987
  accessHintForGuard,
23988
+ accountability,
21865
23989
  advanceVersion,
21866
23990
  ai,
23991
+ asSurfaceError,
21867
23992
  audit,
21868
23993
  autoTrackNode,
21869
23994
  batch,
@@ -21887,6 +24012,7 @@ var version = "0.0.0";
21887
24012
  cqrs,
21888
24013
  createDagCborCodec,
21889
24014
  createDagCborZstdCodec,
24015
+ createGraph,
21890
24016
  createTransport,
21891
24017
  createVersioning,
21892
24018
  createWatermarkController,
@@ -21898,11 +24024,13 @@ var version = "0.0.0";
21898
24024
  defaultConfig,
21899
24025
  defaultHash,
21900
24026
  delay,
24027
+ deleteSnapshot,
21901
24028
  demoShell,
21902
24029
  derived,
21903
24030
  deserializeError,
21904
24031
  dictStorage,
21905
24032
  diffForWAL,
24033
+ diffSnapshots,
21906
24034
  distill,
21907
24035
  distinctUntilChanged,
21908
24036
  domainTemplates,
@@ -21914,6 +24042,7 @@ var version = "0.0.0";
21914
24042
  encodeEnvelope,
21915
24043
  escapeRegexChar,
21916
24044
  exhaustMap,
24045
+ explainPath,
21917
24046
  exponential,
21918
24047
  externalBundle,
21919
24048
  externalProducer,
@@ -21954,6 +24083,7 @@ var version = "0.0.0";
21954
24083
  fromPromise,
21955
24084
  fromPulsar,
21956
24085
  fromRabbitMQ,
24086
+ fromRaf,
21957
24087
  fromRedisStream,
21958
24088
  fromSSE,
21959
24089
  fromSqlite,
@@ -21968,6 +24098,7 @@ var version = "0.0.0";
21968
24098
  graph,
21969
24099
  graphProfile,
21970
24100
  graphspec,
24101
+ guarded,
21971
24102
  harness,
21972
24103
  indexedDbStorage,
21973
24104
  interval,
@@ -21977,7 +24108,9 @@ var version = "0.0.0";
21977
24108
  keepalive,
21978
24109
  last,
21979
24110
  layout,
24111
+ lens,
21980
24112
  linear,
24113
+ listSnapshots,
21981
24114
  lru,
21982
24115
  map,
21983
24116
  matchesAnyPattern,
@@ -22027,11 +24160,15 @@ var version = "0.0.0";
22027
24160
  replay,
22028
24161
  replayWAL,
22029
24162
  rescue,
24163
+ resilientPipeline,
22030
24164
  resolveBackoffPreset,
22031
24165
  resolveDescribeFields,
24166
+ restoreSnapshot,
22032
24167
  retry,
22033
24168
  retrySource,
24169
+ runReduction,
22034
24170
  sample,
24171
+ saveSnapshot,
22035
24172
  scan,
22036
24173
  serializeError,
22037
24174
  share,
@@ -22043,6 +24180,7 @@ var version = "0.0.0";
22043
24180
  solid,
22044
24181
  sqliteStorage,
22045
24182
  state,
24183
+ surface,
22046
24184
  svelte,
22047
24185
  switchMap,
22048
24186
  take,
@@ -22080,6 +24218,7 @@ var version = "0.0.0";
22080
24218
  version,
22081
24219
  vue,
22082
24220
  wallClockNs,
24221
+ watchTopologyTree,
22083
24222
  window,
22084
24223
  windowCount,
22085
24224
  windowTime,