@graphrefly/graphrefly 0.16.0 → 0.18.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 (75) hide show
  1. package/dist/{chunk-RLVFZDCE.js → chunk-76YPZQTW.js} +3 -9
  2. package/dist/{chunk-RLVFZDCE.js.map → chunk-76YPZQTW.js.map} +1 -1
  3. package/dist/{chunk-VZY2B2LU.js → chunk-BV3TPSBK.js} +1 -2
  4. package/dist/chunk-BV3TPSBK.js.map +1 -0
  5. package/dist/{chunk-YX263TXI.js → chunk-F6ORUNO7.js} +19 -52
  6. package/dist/chunk-F6ORUNO7.js.map +1 -0
  7. package/dist/chunk-FCLROC4Q.js +231 -0
  8. package/dist/chunk-FCLROC4Q.js.map +1 -0
  9. package/dist/{chunk-ITDVOCFO.js → chunk-J7S54G7I.js} +2 -3
  10. package/dist/{chunk-26A4E7J7.js → chunk-KJGUP35I.js} +4 -10
  11. package/dist/chunk-KJGUP35I.js.map +1 -0
  12. package/dist/{chunk-3BLRREFM.js → chunk-LB3RYLSC.js} +207 -174
  13. package/dist/chunk-LB3RYLSC.js.map +1 -0
  14. package/dist/{chunk-LKP7IWRV.js → chunk-TNKODJ6E.js} +3 -7
  15. package/dist/chunk-TNKODJ6E.js.map +1 -0
  16. package/dist/{chunk-RZSQ7P2C.js → chunk-UVWEKTYC.js} +3 -3
  17. package/dist/compat/nestjs/index.cjs +221 -225
  18. package/dist/compat/nestjs/index.cjs.map +1 -1
  19. package/dist/compat/nestjs/index.d.cts +4 -4
  20. package/dist/compat/nestjs/index.d.ts +4 -4
  21. package/dist/compat/nestjs/index.js +7 -13
  22. package/dist/core/index.cjs +0 -84
  23. package/dist/core/index.cjs.map +1 -1
  24. package/dist/core/index.d.cts +2 -2
  25. package/dist/core/index.d.ts +2 -2
  26. package/dist/core/index.js +3 -7
  27. package/dist/extra/index.cjs +17 -54
  28. package/dist/extra/index.cjs.map +1 -1
  29. package/dist/extra/index.d.cts +4 -4
  30. package/dist/extra/index.d.ts +4 -4
  31. package/dist/extra/index.js +3 -9
  32. package/dist/graph/index.cjs +329 -174
  33. package/dist/graph/index.cjs.map +1 -1
  34. package/dist/graph/index.d.cts +3 -3
  35. package/dist/graph/index.d.ts +3 -3
  36. package/dist/graph/index.js +10 -6
  37. package/dist/{graph-fCsaaVIa.d.cts → graph-BYFlyNpX.d.cts} +47 -45
  38. package/dist/{graph-Dc-P9BVm.d.ts → graph-gISB9n3n.d.ts} +47 -45
  39. package/dist/{index-N704txAA.d.ts → index-7WnwgjMu.d.ts} +5 -7
  40. package/dist/{index-DWq0P9T6.d.ts → index-B43mC7uY.d.cts} +5 -7
  41. package/dist/{index-BmoUvOGN.d.ts → index-B80mMeuf.d.ts} +2 -4
  42. package/dist/{index-DlGMf_Qe.d.cts → index-BqOWSFhr.d.cts} +2 -2
  43. package/dist/{index-BBVBYPxr.d.cts → index-CEDaJaYE.d.ts} +5 -7
  44. package/dist/{index-DhXznWyH.d.ts → index-CgKPpiu8.d.ts} +2 -2
  45. package/dist/{index-Db27z6Ki.d.cts → index-Ci_vPaVm.d.cts} +90 -7
  46. package/dist/{index-BR19vQME.d.ts → index-DKaB2x0T.d.ts} +90 -7
  47. package/dist/{index-ClaKZFPl.d.cts → index-D_tUMcpz.d.cts} +5 -7
  48. package/dist/{index-YlOH1Gw6.d.cts → index-EmzYk-TG.d.cts} +2 -4
  49. package/dist/index.cjs +503 -282
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +99 -18
  52. package/dist/index.d.ts +99 -18
  53. package/dist/index.js +170 -63
  54. package/dist/index.js.map +1 -1
  55. package/dist/{meta-BV4pj9ML.d.cts → meta-npl5b97j.d.cts} +1 -53
  56. package/dist/{meta-BV4pj9ML.d.ts → meta-npl5b97j.d.ts} +1 -53
  57. package/dist/observable-DFBCBELR.d.cts +36 -0
  58. package/dist/observable-oAGygKvc.d.ts +36 -0
  59. package/dist/patterns/reactive-layout/index.cjs +204 -172
  60. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  61. package/dist/patterns/reactive-layout/index.d.cts +3 -3
  62. package/dist/patterns/reactive-layout/index.d.ts +3 -3
  63. package/dist/patterns/reactive-layout/index.js +4 -4
  64. package/package.json +1 -1
  65. package/dist/chunk-26A4E7J7.js.map +0 -1
  66. package/dist/chunk-3BLRREFM.js.map +0 -1
  67. package/dist/chunk-LKP7IWRV.js.map +0 -1
  68. package/dist/chunk-SHRJH2DN.js +0 -107
  69. package/dist/chunk-SHRJH2DN.js.map +0 -1
  70. package/dist/chunk-VZY2B2LU.js.map +0 -1
  71. package/dist/chunk-YX263TXI.js.map +0 -1
  72. package/dist/observable-Cz-AWhwR.d.cts +0 -42
  73. package/dist/observable-DCqlwGyl.d.ts +0 -42
  74. /package/dist/{chunk-ITDVOCFO.js.map → chunk-J7S54G7I.js.map} +0 -0
  75. /package/dist/{chunk-RZSQ7P2C.js.map → chunk-UVWEKTYC.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -129,7 +129,6 @@ __export(index_exports, {
129
129
  delay: () => delay,
130
130
  demoShell: () => demo_shell_exports,
131
131
  derived: () => derived,
132
- describeNode: () => describeNode,
133
132
  deserializeError: () => deserializeError,
134
133
  distill: () => distill,
135
134
  distinctUntilChanged: () => distinctUntilChanged,
@@ -184,6 +183,7 @@ __export(index_exports, {
184
183
  fromWebhook: () => fromWebhook,
185
184
  globToRegExp: () => globToRegExp,
186
185
  graph: () => graph_exports,
186
+ graphProfile: () => graphProfile,
187
187
  graphspec: () => graphspec_exports,
188
188
  harness: () => harness_exports,
189
189
  interval: () => interval,
@@ -207,7 +207,6 @@ __export(index_exports, {
207
207
  mergeMap: () => mergeMap,
208
208
  messageTier: () => messageTier,
209
209
  messaging: () => messaging_exports,
210
- metaSnapshot: () => metaSnapshot,
211
210
  monotonicNs: () => monotonicNs,
212
211
  nameToSignal: () => nameToSignal,
213
212
  nanostores: () => nanostores_exports,
@@ -216,8 +215,6 @@ __export(index_exports, {
216
215
  never: () => never,
217
216
  node: () => node,
218
217
  normalizeActor: () => normalizeActor,
219
- observeGraph$: () => observeGraph$,
220
- observeNode$: () => observeNode$,
221
218
  of: () => of,
222
219
  orchestration: () => orchestration_exports,
223
220
  pairwise: () => pairwise,
@@ -262,6 +259,7 @@ __export(index_exports, {
262
259
  shareReplay: () => shareReplay,
263
260
  signalToName: () => signalToName,
264
261
  signals: () => signals_exports,
262
+ sizeof: () => sizeof,
265
263
  skip: () => skip,
266
264
  solid: () => solid_exports,
267
265
  startWith: () => startWith,
@@ -283,7 +281,6 @@ __export(index_exports, {
283
281
  toFile: () => toFile,
284
282
  toKafka: () => toKafka,
285
283
  toLoki: () => toLoki,
286
- toMessages$: () => toMessages$,
287
284
  toMongo: () => toMongo,
288
285
  toNATS: () => toNATS,
289
286
  toObservable: () => toObservable,
@@ -1184,7 +1181,6 @@ var NodeImpl = class {
1184
1181
  this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
1185
1182
  return;
1186
1183
  }
1187
- this._cached = value;
1188
1184
  this._downInternal(wasDirty ? [[DATA, value]] : [[DIRTY], [DATA, value]]);
1189
1185
  }
1190
1186
  _runFn() {
@@ -2165,58 +2161,35 @@ __export(nestjs_exports, {
2165
2161
  getActor: () => getActor,
2166
2162
  getGraphToken: () => getGraphToken,
2167
2163
  getNodeToken: () => getNodeToken,
2168
- observeGraph$: () => observeGraph$,
2169
- observeNode$: () => observeNode$,
2170
2164
  observeSSE: () => observeSSE,
2171
2165
  observeSubscription: () => observeSubscription,
2172
- toMessages$: () => toMessages$,
2173
2166
  toObservable: () => toObservable
2174
2167
  });
2175
2168
 
2176
2169
  // src/extra/observable.ts
2177
2170
  var import_rxjs = require("rxjs");
2178
- function toObservable(node2) {
2179
- return new import_rxjs.Observable((subscriber) => {
2180
- const unsub = node2.subscribe((msgs) => {
2181
- for (const m of msgs) {
2171
+ function toObservable(node2, options) {
2172
+ if (options?.raw) {
2173
+ return new import_rxjs.Observable((subscriber) => {
2174
+ const unsub = node2.subscribe((msgs) => {
2182
2175
  if (subscriber.closed) return;
2183
- if (m[0] === DATA) {
2184
- subscriber.next(m[1]);
2185
- } else if (m[0] === ERROR) {
2186
- subscriber.error(m[1]);
2187
- return;
2188
- } else if (m[0] === COMPLETE) {
2189
- subscriber.complete();
2190
- return;
2176
+ subscriber.next(msgs);
2177
+ for (const m of msgs) {
2178
+ if (m[0] === ERROR) {
2179
+ subscriber.error(m[1]);
2180
+ return;
2181
+ }
2182
+ if (m[0] === COMPLETE) {
2183
+ subscriber.complete();
2184
+ return;
2185
+ }
2191
2186
  }
2192
- }
2187
+ });
2188
+ return unsub;
2193
2189
  });
2194
- return unsub;
2195
- });
2196
- }
2197
- function toMessages$(node2) {
2190
+ }
2198
2191
  return new import_rxjs.Observable((subscriber) => {
2199
2192
  const unsub = node2.subscribe((msgs) => {
2200
- if (subscriber.closed) return;
2201
- subscriber.next(msgs);
2202
- for (const m of msgs) {
2203
- if (m[0] === ERROR) {
2204
- subscriber.error(m[1]);
2205
- return;
2206
- }
2207
- if (m[0] === COMPLETE) {
2208
- subscriber.complete();
2209
- return;
2210
- }
2211
- }
2212
- });
2213
- return unsub;
2214
- });
2215
- }
2216
- function observeNode$(graph, path, options) {
2217
- return new import_rxjs.Observable((subscriber) => {
2218
- const handle = graph.observe(path, options);
2219
- const unsub = handle.subscribe((msgs) => {
2220
2193
  for (const m of msgs) {
2221
2194
  if (subscriber.closed) return;
2222
2195
  if (m[0] === DATA) {
@@ -2233,16 +2206,6 @@ function observeNode$(graph, path, options) {
2233
2206
  return unsub;
2234
2207
  });
2235
2208
  }
2236
- function observeGraph$(graph, options) {
2237
- return new import_rxjs.Observable((subscriber) => {
2238
- const handle = graph.observe(options);
2239
- const unsub = handle.subscribe((nodePath, messages) => {
2240
- if (subscriber.closed) return;
2241
- subscriber.next({ path: nodePath, messages });
2242
- });
2243
- return unsub;
2244
- });
2245
- }
2246
2209
 
2247
2210
  // src/compat/nestjs/decorators.ts
2248
2211
  var import_common = require("@nestjs/common");
@@ -3789,7 +3752,7 @@ var RingBuffer = class {
3789
3752
  return result;
3790
3753
  }
3791
3754
  };
3792
- var SPY_ANSI_THEME = {
3755
+ var OBSERVE_ANSI_THEME = {
3793
3756
  data: "\x1B[32m",
3794
3757
  dirty: "\x1B[33m",
3795
3758
  resolved: "\x1B[36m",
@@ -3799,7 +3762,7 @@ var SPY_ANSI_THEME = {
3799
3762
  path: "\x1B[90m",
3800
3763
  reset: "\x1B[0m"
3801
3764
  };
3802
- var SPY_NO_COLOR_THEME = {
3765
+ var OBSERVE_NO_COLOR_THEME = {
3803
3766
  data: "",
3804
3767
  dirty: "",
3805
3768
  resolved: "",
@@ -3819,9 +3782,9 @@ function describeData(value) {
3819
3782
  return "[unserializable]";
3820
3783
  }
3821
3784
  }
3822
- function resolveSpyTheme(theme) {
3823
- if (theme === "none") return SPY_NO_COLOR_THEME;
3824
- if (theme === "ansi" || theme == null) return SPY_ANSI_THEME;
3785
+ function resolveObserveTheme(theme) {
3786
+ if (theme === "none") return OBSERVE_NO_COLOR_THEME;
3787
+ if (theme === "ansi" || theme == null) return OBSERVE_ANSI_THEME;
3825
3788
  return {
3826
3789
  data: theme.data ?? "",
3827
3790
  dirty: theme.dirty ?? "",
@@ -4592,9 +4555,13 @@ var Graph = class _Graph {
4592
4555
  if (actor2 != null && !target.allowsObserve(actor2)) {
4593
4556
  throw new GuardDenied({ actor: actor2, action: "observe", nodeName: path });
4594
4557
  }
4595
- const wantsStructured2 = resolved.structured === true || resolved.timeline === true || resolved.causal === true || resolved.derived === true || resolved.detail === "minimal" || resolved.detail === "full";
4596
- if (wantsStructured2 && _Graph.inspectorEnabled) {
4597
- return this._createObserveResult(path, target, resolved);
4558
+ const wantsStructured2 = resolved.structured === true || resolved.timeline === true || resolved.causal === true || resolved.derived === true || resolved.detail === "minimal" || resolved.detail === "full" || resolved.format != null;
4559
+ if (wantsStructured2) {
4560
+ const result = _Graph.inspectorEnabled ? this._createObserveResult(path, target, resolved) : this._createFallbackObserveResult(path, resolved);
4561
+ if (resolved.format != null) {
4562
+ this._attachFormatLogger(result, resolved);
4563
+ }
4564
+ return result;
4598
4565
  }
4599
4566
  return {
4600
4567
  subscribe(sink) {
@@ -4612,9 +4579,13 @@ var Graph = class _Graph {
4612
4579
  }
4613
4580
  const opts = resolveObserveDetail(pathOrOpts);
4614
4581
  const actor = opts.actor;
4615
- const wantsStructured = opts.structured === true || opts.timeline === true || opts.causal === true || opts.derived === true || opts.detail === "minimal" || opts.detail === "full";
4616
- if (wantsStructured && _Graph.inspectorEnabled) {
4617
- return this._createObserveResultForAll(opts);
4582
+ const wantsStructured = opts.structured === true || opts.timeline === true || opts.causal === true || opts.derived === true || opts.detail === "minimal" || opts.detail === "full" || opts.format != null;
4583
+ if (wantsStructured) {
4584
+ const result = _Graph.inspectorEnabled ? this._createObserveResultForAll(opts) : this._createFallbackObserveResultForAll(opts);
4585
+ if (opts.format != null) {
4586
+ this._attachFormatLogger(result, opts);
4587
+ }
4588
+ return result;
4618
4589
  }
4619
4590
  return {
4620
4591
  subscribe: (sink) => {
@@ -4658,6 +4629,7 @@ var Graph = class _Graph {
4658
4629
  let lastTriggerDepIndex;
4659
4630
  let lastRunDepValues;
4660
4631
  let detachInspectorHook;
4632
+ let batchSeq = 0;
4661
4633
  if ((causal || derived2) && target instanceof NodeImpl) {
4662
4634
  detachInspectorHook = target._setInspectorHook((event) => {
4663
4635
  if (event.kind === "dep_message") {
@@ -4670,15 +4642,16 @@ var Graph = class _Graph {
4670
4642
  type: "derived",
4671
4643
  path,
4672
4644
  dep_values: [...event.depValues],
4673
- ...timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching() } : {}
4645
+ ...timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching(), batch_id: batchSeq } : {}
4674
4646
  });
4675
4647
  }
4676
4648
  });
4677
4649
  }
4678
4650
  const unsub = target.subscribe((msgs) => {
4651
+ batchSeq++;
4679
4652
  for (const m of msgs) {
4680
4653
  const t = m[0];
4681
- const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching() } : {};
4654
+ const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching(), batch_id: batchSeq } : {};
4682
4655
  const withCausal = causal && lastRunDepValues != null ? (() => {
4683
4656
  const triggerDep = lastTriggerDepIndex != null && lastTriggerDepIndex >= 0 && target instanceof NodeImpl ? target._deps[lastTriggerDepIndex] : void 0;
4684
4657
  const tv = triggerDep?.v;
@@ -4747,11 +4720,15 @@ var Graph = class _Graph {
4747
4720
  Object.assign(merged, extra);
4748
4721
  }
4749
4722
  const resolvedTarget = graph.resolve(basePath);
4750
- return graph._createObserveResult(
4723
+ const expanded = graph._createObserveResult(
4751
4724
  basePath,
4752
4725
  resolvedTarget,
4753
4726
  resolveObserveDetail(merged)
4754
4727
  );
4728
+ if (merged.format != null) {
4729
+ graph._attachFormatLogger(expanded, merged);
4730
+ }
4731
+ return expanded;
4755
4732
  }
4756
4733
  };
4757
4734
  }
@@ -4771,11 +4748,13 @@ var Graph = class _Graph {
4771
4748
  this._collectObserveTargets("", targets);
4772
4749
  targets.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
4773
4750
  const picked = actor == null ? targets : targets.filter(([, nd]) => nd.allowsObserve(actor));
4751
+ let batchSeq = 0;
4774
4752
  const unsubs = picked.map(
4775
4753
  ([path, nd]) => nd.subscribe((msgs) => {
4754
+ batchSeq++;
4776
4755
  for (const m of msgs) {
4777
4756
  const t = m[0];
4778
- const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching() } : {};
4757
+ const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching(), batch_id: batchSeq } : {};
4779
4758
  if (t === DATA) {
4780
4759
  result.values[path] = m[1];
4781
4760
  result.events.push({ type: "data", path, data: m[1], ...base });
@@ -4831,25 +4810,161 @@ var Graph = class _Graph {
4831
4810
  } else {
4832
4811
  Object.assign(merged, extra);
4833
4812
  }
4834
- return graph._createObserveResultForAll(resolveObserveDetail(merged));
4813
+ const expanded = graph._createObserveResultForAll(resolveObserveDetail(merged));
4814
+ if (merged.format != null) {
4815
+ graph._attachFormatLogger(expanded, merged);
4816
+ }
4817
+ return expanded;
4835
4818
  }
4836
4819
  };
4837
4820
  }
4838
4821
  /**
4839
- * Convenience live debugger over {@link Graph.observe}. Logs protocol events as they flow.
4840
- *
4841
- * Supports one-node (`path`) and graph-wide modes, event filtering, and JSON/pretty rendering.
4842
- * Color themes are built in (`ansi` / `none`) to avoid external dependencies.
4843
- *
4844
- * @param options - Spy configuration.
4845
- * @returns Disposable handle plus a structured observation accumulator.
4822
+ * Fallback ObserveResult for single-node when inspector is disabled but `format` is requested.
4823
+ * Subscribes to raw messages and accumulates events with timeline info.
4824
+ */
4825
+ _createFallbackObserveResult(path, options) {
4826
+ const timeline = options.timeline !== false;
4827
+ const acc = {
4828
+ values: {},
4829
+ dirtyCount: 0,
4830
+ resolvedCount: 0,
4831
+ events: [],
4832
+ completedCleanly: false,
4833
+ errored: false
4834
+ };
4835
+ const target = this.resolve(path);
4836
+ let batchSeq = 0;
4837
+ const unsub = target.subscribe((msgs) => {
4838
+ batchSeq++;
4839
+ for (const m of msgs) {
4840
+ const t = m[0];
4841
+ const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching(), batch_id: batchSeq } : {};
4842
+ if (t === DATA) {
4843
+ acc.values[path] = m[1];
4844
+ acc.events.push({ type: "data", path, data: m[1], ...base });
4845
+ } else if (t === DIRTY) {
4846
+ acc.dirtyCount++;
4847
+ acc.events.push({ type: "dirty", path, ...base });
4848
+ } else if (t === RESOLVED) {
4849
+ acc.resolvedCount++;
4850
+ acc.events.push({ type: "resolved", path, ...base });
4851
+ } else if (t === COMPLETE) {
4852
+ if (!acc.errored) acc.completedCleanly = true;
4853
+ acc.events.push({ type: "complete", path, ...base });
4854
+ } else if (t === ERROR) {
4855
+ acc.errored = true;
4856
+ acc.events.push({ type: "error", path, data: m[1], ...base });
4857
+ }
4858
+ }
4859
+ });
4860
+ return {
4861
+ get values() {
4862
+ return acc.values;
4863
+ },
4864
+ get dirtyCount() {
4865
+ return acc.dirtyCount;
4866
+ },
4867
+ get resolvedCount() {
4868
+ return acc.resolvedCount;
4869
+ },
4870
+ get events() {
4871
+ return acc.events;
4872
+ },
4873
+ get completedCleanly() {
4874
+ return acc.completedCleanly;
4875
+ },
4876
+ get errored() {
4877
+ return acc.errored;
4878
+ },
4879
+ dispose() {
4880
+ unsub();
4881
+ },
4882
+ expand() {
4883
+ throw new Error("expand() requires inspector mode (Graph.inspectorEnabled = true)");
4884
+ }
4885
+ };
4886
+ }
4887
+ /**
4888
+ * Fallback ObserveResult for graph-wide when inspector is disabled but `format` is requested.
4889
+ */
4890
+ _createFallbackObserveResultForAll(options) {
4891
+ const timeline = options.timeline !== false;
4892
+ const actor = options.actor;
4893
+ const acc = {
4894
+ values: {},
4895
+ dirtyCount: 0,
4896
+ resolvedCount: 0,
4897
+ events: [],
4898
+ completedCleanly: false,
4899
+ errored: false
4900
+ };
4901
+ const targets = [];
4902
+ this._collectObserveTargets("", targets);
4903
+ targets.sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
4904
+ const picked = actor == null ? targets : targets.filter(([, nd]) => nd.allowsObserve(actor));
4905
+ let batchSeq = 0;
4906
+ const unsubs = picked.map(
4907
+ ([path, nd]) => nd.subscribe((msgs) => {
4908
+ batchSeq++;
4909
+ for (const m of msgs) {
4910
+ const t = m[0];
4911
+ const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching(), batch_id: batchSeq } : {};
4912
+ if (t === DATA) {
4913
+ acc.values[path] = m[1];
4914
+ acc.events.push({ type: "data", path, data: m[1], ...base });
4915
+ } else if (t === DIRTY) {
4916
+ acc.dirtyCount++;
4917
+ acc.events.push({ type: "dirty", path, ...base });
4918
+ } else if (t === RESOLVED) {
4919
+ acc.resolvedCount++;
4920
+ acc.events.push({ type: "resolved", path, ...base });
4921
+ } else if (t === COMPLETE) {
4922
+ if (!acc.errored) acc.completedCleanly = true;
4923
+ acc.events.push({ type: "complete", path, ...base });
4924
+ } else if (t === ERROR) {
4925
+ acc.errored = true;
4926
+ acc.events.push({ type: "error", path, data: m[1], ...base });
4927
+ }
4928
+ }
4929
+ })
4930
+ );
4931
+ return {
4932
+ get values() {
4933
+ return acc.values;
4934
+ },
4935
+ get dirtyCount() {
4936
+ return acc.dirtyCount;
4937
+ },
4938
+ get resolvedCount() {
4939
+ return acc.resolvedCount;
4940
+ },
4941
+ get events() {
4942
+ return acc.events;
4943
+ },
4944
+ get completedCleanly() {
4945
+ return acc.completedCleanly;
4946
+ },
4947
+ get errored() {
4948
+ return acc.errored;
4949
+ },
4950
+ dispose() {
4951
+ for (const u of unsubs) u();
4952
+ },
4953
+ expand() {
4954
+ throw new Error("expand() requires inspector mode (Graph.inspectorEnabled = true)");
4955
+ }
4956
+ };
4957
+ }
4958
+ /**
4959
+ * Attaches a format logger to an ObserveResult, rendering events as they arrive.
4960
+ * Wraps the result's dispose to flush pending events.
4846
4961
  */
4847
- spy(options = {}) {
4962
+ _attachFormatLogger(result, options) {
4963
+ const format = options.format;
4964
+ const logger = options.logger ?? ((line) => console.log(line));
4848
4965
  const include = options.includeTypes ? new Set(options.includeTypes) : null;
4849
4966
  const exclude = options.excludeTypes ? new Set(options.excludeTypes) : null;
4850
- const theme = resolveSpyTheme(options.theme);
4851
- const format = options.format ?? "pretty";
4852
- const logger = options.logger ?? ((line) => console.log(line));
4967
+ const theme = resolveObserveTheme(options.theme);
4853
4968
  const shouldLog = (type) => {
4854
4969
  if (include?.has(type) === false) return false;
4855
4970
  if (exclude?.has(type) === true) return false;
@@ -4874,133 +4989,26 @@ var Graph = class _Graph {
4874
4989
  const batchPart = event.in_batch ? " [batch]" : "";
4875
4990
  return `${pathPart}${color}${event.type.toUpperCase()}${theme.reset}${dataPart}${triggerPart}${batchPart}`;
4876
4991
  };
4877
- if (!_Graph.inspectorEnabled) {
4878
- const timeline = options.timeline ?? true;
4879
- const acc = {
4880
- values: {},
4881
- dirtyCount: 0,
4882
- resolvedCount: 0,
4883
- events: [],
4884
- completedCleanly: false,
4885
- errored: false
4886
- };
4887
- let stop2 = () => {
4888
- };
4889
- const result2 = {
4890
- get values() {
4891
- return acc.values;
4892
- },
4893
- get dirtyCount() {
4894
- return acc.dirtyCount;
4895
- },
4896
- get resolvedCount() {
4897
- return acc.resolvedCount;
4898
- },
4899
- get events() {
4900
- return acc.events;
4901
- },
4902
- get completedCleanly() {
4903
- return acc.completedCleanly;
4904
- },
4905
- get errored() {
4906
- return acc.errored;
4907
- },
4908
- dispose() {
4909
- stop2();
4910
- },
4911
- expand() {
4912
- throw new Error("expand() requires inspector mode (Graph.inspectorEnabled = true)");
4913
- }
4914
- };
4915
- const pushEvent = (path, message) => {
4916
- const t = message[0];
4917
- const base = timeline ? { timestamp_ns: monotonicNs(), in_batch: isBatching() } : {};
4918
- let event;
4919
- if (t === DATA) {
4920
- if (path != null) acc.values[path] = message[1];
4921
- event = { type: "data", ...path != null ? { path } : {}, data: message[1], ...base };
4922
- } else if (t === DIRTY) {
4923
- acc.dirtyCount += 1;
4924
- event = { type: "dirty", ...path != null ? { path } : {}, ...base };
4925
- } else if (t === RESOLVED) {
4926
- acc.resolvedCount += 1;
4927
- event = { type: "resolved", ...path != null ? { path } : {}, ...base };
4928
- } else if (t === COMPLETE) {
4929
- if (!acc.errored) acc.completedCleanly = true;
4930
- event = { type: "complete", ...path != null ? { path } : {}, ...base };
4931
- } else if (t === ERROR) {
4932
- acc.errored = true;
4933
- event = {
4934
- type: "error",
4935
- ...path != null ? { path } : {},
4936
- data: message[1],
4937
- ...base
4938
- };
4992
+ let cursor = 0;
4993
+ const flush = () => {
4994
+ const events = result.events;
4995
+ while (cursor < events.length) {
4996
+ const event = events[cursor++];
4997
+ if (shouldLog(event.type)) {
4998
+ logger(renderEvent(event), event);
4939
4999
  }
4940
- if (!event) return;
4941
- acc.events.push(event);
4942
- if (!shouldLog(event.type)) return;
4943
- logger(renderEvent(event), event);
4944
- };
4945
- if (options.path != null) {
4946
- const stream2 = this.observe(options.path, {
4947
- actor: options.actor,
4948
- structured: false
4949
- });
4950
- stop2 = stream2.subscribe((messages) => {
4951
- for (const m of messages) {
4952
- pushEvent(options.path, m);
4953
- }
4954
- });
4955
- } else {
4956
- const stream2 = this.observe({ actor: options.actor, structured: false });
4957
- stop2 = stream2.subscribe((path, messages) => {
4958
- for (const m of messages) {
4959
- pushEvent(path, m);
4960
- }
4961
- });
4962
5000
  }
4963
- return {
4964
- result: result2,
4965
- dispose() {
4966
- result2.dispose();
4967
- }
4968
- };
4969
- }
4970
- const structuredObserveOptions = {
4971
- actor: options.actor,
4972
- structured: true,
4973
- ...options.timeline !== false ? { timeline: true } : {},
4974
- ...options.causal ? { causal: true } : {},
4975
- ...options.derived ? { derived: true } : {}
4976
5001
  };
4977
- const result = options.path != null ? this.observe(options.path, structuredObserveOptions) : this.observe(structuredObserveOptions);
4978
- let cursor = 0;
4979
- const flushNewEvents = () => {
4980
- const nextEvents = result.events.slice(cursor);
4981
- cursor = result.events.length;
4982
- for (const event of nextEvents) {
4983
- if (!shouldLog(event.type)) continue;
4984
- logger(renderEvent(event), event);
4985
- }
5002
+ const origPush = result.events.push;
5003
+ result.events.push = function(...items) {
5004
+ const ret = origPush.apply(this, items);
5005
+ flush();
5006
+ return ret;
4986
5007
  };
4987
- const stream = options.path != null ? this.observe(options.path, { actor: options.actor, structured: false }) : this.observe({ actor: options.actor, structured: false });
4988
- const stop = options.path != null ? stream.subscribe((messages) => {
4989
- if (messages.length > 0) {
4990
- flushNewEvents();
4991
- }
4992
- }) : stream.subscribe((_path, messages) => {
4993
- if (messages.length > 0) {
4994
- flushNewEvents();
4995
- }
4996
- });
4997
- return {
4998
- result,
4999
- dispose() {
5000
- stop();
5001
- flushNewEvents();
5002
- result.dispose();
5003
- }
5008
+ const origDispose = result.dispose.bind(result);
5009
+ result.dispose = () => {
5010
+ origDispose();
5011
+ flush();
5004
5012
  };
5005
5013
  }
5006
5014
  /**
@@ -5395,33 +5403,21 @@ var Graph = class _Graph {
5395
5403
  // ——————————————————————————————————————————————————————————————
5396
5404
  /**
5397
5405
  * When `false`, structured observation options (`causal`, `timeline`),
5398
- * `annotate()`, and `traceLog()` are no-ops. Raw `observe()` always works.
5406
+ * and `trace()` writes are no-ops. Raw `observe()` always works.
5399
5407
  *
5400
5408
  * Default: `true` outside production (`process.env.NODE_ENV !== "production"`).
5401
5409
  */
5402
5410
  static inspectorEnabled = !(typeof process !== "undefined" && process.env?.NODE_ENV === "production");
5403
5411
  _annotations = /* @__PURE__ */ new Map();
5404
5412
  _traceRing = new RingBuffer(1e3);
5405
- /**
5406
- * Attaches a reasoning annotation to a node — captures *why* an AI agent set a value.
5407
- *
5408
- * No-op when {@link Graph.inspectorEnabled} is `false`.
5409
- *
5410
- * @param path - Qualified node path.
5411
- * @param reason - Free-text note stored in the trace ring buffer.
5412
- */
5413
- annotate(path, reason) {
5414
- if (!_Graph.inspectorEnabled) return;
5415
- this.resolve(path);
5416
- this._annotations.set(path, reason);
5417
- this._traceRing.push({ path, reason, timestamp_ns: monotonicNs() });
5418
- }
5419
- /**
5420
- * Returns a chronological log of all reasoning annotations (ring buffer).
5421
- *
5422
- * @returns `[]` when {@link Graph.inspectorEnabled} is `false`.
5423
- */
5424
- traceLog() {
5413
+ trace(path, reason) {
5414
+ if (path != null && reason != null) {
5415
+ if (!_Graph.inspectorEnabled) return;
5416
+ this.resolve(path);
5417
+ this._annotations.set(path, reason);
5418
+ this._traceRing.push({ path, reason, timestamp_ns: monotonicNs() });
5419
+ return;
5420
+ }
5425
5421
  if (!_Graph.inspectorEnabled) return [];
5426
5422
  return this._traceRing.toArray();
5427
5423
  }
@@ -5584,7 +5580,6 @@ __export(core_exports, {
5584
5580
  createVersioning: () => createVersioning,
5585
5581
  defaultHash: () => defaultHash,
5586
5582
  derived: () => derived,
5587
- describeNode: () => describeNode,
5588
5583
  downWithBatch: () => downWithBatch,
5589
5584
  dynamicNode: () => dynamicNode,
5590
5585
  effect: () => effect,
@@ -5595,7 +5590,6 @@ __export(core_exports, {
5595
5590
  isV1: () => isV1,
5596
5591
  knownMessageTypes: () => knownMessageTypes,
5597
5592
  messageTier: () => messageTier,
5598
- metaSnapshot: () => metaSnapshot,
5599
5593
  monotonicNs: () => monotonicNs,
5600
5594
  node: () => node,
5601
5595
  normalizeActor: () => normalizeActor,
@@ -5797,9 +5791,11 @@ __export(graph_exports, {
5797
5791
  JsonCodec: () => JsonCodec,
5798
5792
  createDagCborCodec: () => createDagCborCodec,
5799
5793
  createDagCborZstdCodec: () => createDagCborZstdCodec,
5794
+ graphProfile: () => graphProfile,
5800
5795
  negotiateCodec: () => negotiateCodec,
5801
5796
  reachable: () => reachable,
5802
- replayWAL: () => replayWAL
5797
+ replayWAL: () => replayWAL,
5798
+ sizeof: () => sizeof
5803
5799
  });
5804
5800
 
5805
5801
  // src/graph/codec.ts
@@ -5878,6 +5874,125 @@ function replayWAL(entries) {
5878
5874
  return result;
5879
5875
  }
5880
5876
 
5877
+ // src/graph/sizeof.ts
5878
+ var OVERHEAD = {
5879
+ object: 56,
5880
+ array: 64,
5881
+ string: 40,
5882
+ // header; content added separately
5883
+ number: 8,
5884
+ boolean: 4,
5885
+ null: 0,
5886
+ undefined: 0,
5887
+ symbol: 40,
5888
+ bigint: 16,
5889
+ function: 120,
5890
+ map: 72,
5891
+ set: 72,
5892
+ mapEntry: 40,
5893
+ setEntry: 24
5894
+ };
5895
+ function sizeof(value) {
5896
+ const seen = /* @__PURE__ */ new WeakSet();
5897
+ return _sizeof(value, seen);
5898
+ }
5899
+ function _sizeof(value, seen) {
5900
+ if (value == null) return 0;
5901
+ const t = typeof value;
5902
+ switch (t) {
5903
+ case "number":
5904
+ return OVERHEAD.number;
5905
+ case "boolean":
5906
+ return OVERHEAD.boolean;
5907
+ case "string":
5908
+ return OVERHEAD.string + value.length * 2;
5909
+ // UTF-16
5910
+ case "bigint":
5911
+ return OVERHEAD.bigint;
5912
+ case "symbol":
5913
+ return OVERHEAD.symbol;
5914
+ case "function":
5915
+ if (seen.has(value)) return 0;
5916
+ seen.add(value);
5917
+ return OVERHEAD.function;
5918
+ case "undefined":
5919
+ return 0;
5920
+ }
5921
+ const obj = value;
5922
+ if (seen.has(obj)) return 0;
5923
+ seen.add(obj);
5924
+ if (obj instanceof Map) {
5925
+ let size2 = OVERHEAD.map;
5926
+ for (const [k, v] of obj) {
5927
+ size2 += OVERHEAD.mapEntry + _sizeof(k, seen) + _sizeof(v, seen);
5928
+ }
5929
+ return size2;
5930
+ }
5931
+ if (obj instanceof Set) {
5932
+ let size2 = OVERHEAD.set;
5933
+ for (const v of obj) {
5934
+ size2 += OVERHEAD.setEntry + _sizeof(v, seen);
5935
+ }
5936
+ return size2;
5937
+ }
5938
+ if (Array.isArray(obj)) {
5939
+ let size2 = OVERHEAD.array + obj.length * 8;
5940
+ for (const item of obj) {
5941
+ size2 += _sizeof(item, seen);
5942
+ }
5943
+ return size2;
5944
+ }
5945
+ if (obj instanceof ArrayBuffer) return obj.byteLength;
5946
+ if (ArrayBuffer.isView(obj)) return obj.byteLength;
5947
+ let size = OVERHEAD.object;
5948
+ const keys = Object.keys(obj);
5949
+ for (const key of keys) {
5950
+ size += OVERHEAD.string + key.length * 2;
5951
+ size += _sizeof(obj[key], seen);
5952
+ }
5953
+ return size;
5954
+ }
5955
+
5956
+ // src/graph/profile.ts
5957
+ function graphProfile(graph, opts) {
5958
+ const topN = opts?.topN ?? 10;
5959
+ const desc = graph.describe({ detail: "standard" });
5960
+ const targets = [];
5961
+ if (typeof graph._collectObserveTargets === "function") {
5962
+ graph._collectObserveTargets("", targets);
5963
+ }
5964
+ const pathToNode = /* @__PURE__ */ new Map();
5965
+ for (const [p, n] of targets) {
5966
+ pathToNode.set(p, n);
5967
+ }
5968
+ const profiles = [];
5969
+ for (const [path, nodeDesc] of Object.entries(desc.nodes)) {
5970
+ const nd = pathToNode.get(path);
5971
+ const impl = nd instanceof NodeImpl ? nd : null;
5972
+ const valueSizeBytes = impl ? sizeof(impl.get()) : 0;
5973
+ const subscriberCount = impl ? impl._sinkCount : 0;
5974
+ const depCount = nodeDesc.deps?.length ?? 0;
5975
+ profiles.push({
5976
+ path,
5977
+ type: nodeDesc.type,
5978
+ status: nodeDesc.status ?? "unknown",
5979
+ valueSizeBytes,
5980
+ subscriberCount,
5981
+ depCount
5982
+ });
5983
+ }
5984
+ const totalValueSizeBytes = profiles.reduce((sum, p) => sum + p.valueSizeBytes, 0);
5985
+ const hotspots = [...profiles].sort((a, b) => b.valueSizeBytes - a.valueSizeBytes).slice(0, topN);
5986
+ return {
5987
+ nodeCount: profiles.length,
5988
+ edgeCount: desc.edges.length,
5989
+ subgraphCount: desc.subgraphs.length,
5990
+ nodes: profiles,
5991
+ totalValueSizeBytes,
5992
+ hotspots
5993
+ };
5994
+ }
5995
+
5881
5996
  // src/patterns/cqrs.ts
5882
5997
  var COMMAND_GUARD = policy((allow, deny) => {
5883
5998
  allow("write");
@@ -6957,8 +7072,6 @@ __export(extra_exports, {
6957
7072
  mergeMap: () => mergeMap,
6958
7073
  nameToSignal: () => nameToSignal,
6959
7074
  never: () => never,
6960
- observeGraph$: () => observeGraph$,
6961
- observeNode$: () => observeNode$,
6962
7075
  of: () => of,
6963
7076
  pairwise: () => pairwise,
6964
7077
  parseCron: () => parseCron,
@@ -7007,7 +7120,6 @@ __export(extra_exports, {
7007
7120
  toFile: () => toFile,
7008
7121
  toKafka: () => toKafka,
7009
7122
  toLoki: () => toLoki,
7010
- toMessages$: () => toMessages$,
7011
7123
  toMongo: () => toMongo,
7012
7124
  toNATS: () => toNATS,
7013
7125
  toObservable: () => toObservable,
@@ -13376,36 +13488,33 @@ function firstDataFromNode(resolved, opts) {
13376
13488
  }
13377
13489
  const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
13378
13490
  return new Promise((resolve, reject) => {
13379
- let timer;
13380
- const cleanup = () => {
13381
- if (timer !== void 0) clearTimeout(timer);
13382
- };
13491
+ const timer = new ResettableTimer();
13383
13492
  const unsub = resolved.subscribe((messages) => {
13384
13493
  for (const msg of messages) {
13385
13494
  if (msg[0] === DATA) {
13386
- cleanup();
13495
+ timer.cancel();
13387
13496
  unsub();
13388
13497
  resolve(msg[1]);
13389
13498
  return;
13390
13499
  }
13391
13500
  if (msg[0] === ERROR) {
13392
- cleanup();
13501
+ timer.cancel();
13393
13502
  unsub();
13394
13503
  reject(msg[1]);
13395
13504
  return;
13396
13505
  }
13397
13506
  if (msg[0] === COMPLETE) {
13398
- cleanup();
13507
+ timer.cancel();
13399
13508
  unsub();
13400
13509
  reject(new Error("firstDataFromNode: completed without producing a value"));
13401
13510
  return;
13402
13511
  }
13403
13512
  }
13404
13513
  });
13405
- timer = setTimeout(() => {
13514
+ timer.start(timeoutMs, () => {
13406
13515
  unsub();
13407
13516
  reject(new Error(`firstDataFromNode: timed out after ${timeoutMs}ms`));
13408
- }, timeoutMs);
13517
+ });
13409
13518
  });
13410
13519
  }
13411
13520
  async function resolveToolHandlerResult(value) {
@@ -15401,7 +15510,7 @@ function demoShell(opts) {
15401
15510
  ([ref, _tick]) => {
15402
15511
  const demo = ref;
15403
15512
  if (!demo) return [];
15404
- return demo.traceLog();
15513
+ return demo.trace();
15405
15514
  },
15406
15515
  { name: "inspect/trace-log" }
15407
15516
  );
@@ -17347,9 +17456,12 @@ __export(harness_exports, {
17347
17456
  DEFAULT_QUEUE_CONFIGS: () => DEFAULT_QUEUE_CONFIGS,
17348
17457
  DEFAULT_SEVERITY_WEIGHTS: () => DEFAULT_SEVERITY_WEIGHTS,
17349
17458
  HarnessGraph: () => HarnessGraph,
17459
+ QUEUE_NAMES: () => QUEUE_NAMES,
17350
17460
  defaultErrorClassifier: () => defaultErrorClassifier,
17351
17461
  evalIntakeBridge: () => evalIntakeBridge,
17352
17462
  harnessLoop: () => harnessLoop,
17463
+ harnessProfile: () => harnessProfile,
17464
+ harnessTrace: () => harnessTrace,
17353
17465
  priorityScore: () => priorityScore,
17354
17466
  strategyKey: () => strategyKey,
17355
17467
  strategyModel: () => strategyModel
@@ -18250,6 +18362,12 @@ function onFailure(graph, name, source, recover, opts) {
18250
18362
  }
18251
18363
 
18252
18364
  // src/patterns/harness/types.ts
18365
+ var QUEUE_NAMES = [
18366
+ "auto-fix",
18367
+ "needs-decision",
18368
+ "investigation",
18369
+ "backlog"
18370
+ ];
18253
18371
  function strategyKey(rootCause, intervention) {
18254
18372
  return `${rootCause}\u2192${intervention}`;
18255
18373
  }
@@ -18350,8 +18468,8 @@ function priorityScore(item, strategy, lastInteractionNs, urgency, signals) {
18350
18468
  }
18351
18469
 
18352
18470
  // src/patterns/harness/loop.ts
18353
- function baseSummary(summary) {
18354
- return summary.replace(/^\[RETRY \d+\/\d+\]\s*/, "");
18471
+ function trackingKey(item) {
18472
+ return item.relatedTo?.[0] ?? item.summary;
18355
18473
  }
18356
18474
  var DEFAULT_TRIAGE_PROMPT = `You are a triage classifier for a reactive collaboration harness.
18357
18475
 
@@ -18397,12 +18515,6 @@ Output JSON:
18397
18515
  "findings": ["<finding1>", ...],
18398
18516
  "errorClass": "self-correctable" | "structural" // only if verified=false
18399
18517
  }`;
18400
- var QUEUE_NAMES = [
18401
- "auto-fix",
18402
- "needs-decision",
18403
- "investigation",
18404
- "backlog"
18405
- ];
18406
18518
  var HarnessGraph = class extends Graph {
18407
18519
  /** Intake topic — publish items here to enter the loop. */
18408
18520
  intake;
@@ -18414,19 +18526,19 @@ var HarnessGraph = class extends Graph {
18414
18526
  strategy;
18415
18527
  /** Verify results topic — subscribe to see verification outcomes. */
18416
18528
  verifyResults;
18417
- /** Per-item fast-retry counts (keyed by base summary). */
18418
- retryTracker;
18419
- /** Per-item reingestion counts (keyed by base summary). */
18420
- reingestionTracker;
18421
- constructor(name, intake, queues, gates, strategy, verifyResults, retryTracker, reingestionTracker) {
18529
+ /** Global retry count across all items (circuit breaker). Reactive — subscribable. */
18530
+ totalRetries;
18531
+ /** Global reingestion count across all items (circuit breaker). Reactive — subscribable. */
18532
+ totalReingestions;
18533
+ constructor(name, intake, queues, gates, strategy, verifyResults, totalRetries, totalReingestions) {
18422
18534
  super(name);
18423
18535
  this.intake = intake;
18424
18536
  this.queues = queues;
18425
18537
  this.gates = gates;
18426
18538
  this.strategy = strategy;
18427
18539
  this.verifyResults = verifyResults;
18428
- this.retryTracker = retryTracker;
18429
- this.reingestionTracker = reingestionTracker;
18540
+ this.totalRetries = totalRetries;
18541
+ this.totalReingestions = totalReingestions;
18430
18542
  }
18431
18543
  };
18432
18544
  function harnessLoop(name, opts) {
@@ -18468,11 +18580,14 @@ function harnessLoop(name, opts) {
18468
18580
  for (const route of QUEUE_NAMES) {
18469
18581
  queueTopics.set(route, new TopicGraph(`queue/${route}`, { retainedLimit }));
18470
18582
  }
18471
- const router = effect([triageNode], ([triaged]) => {
18472
- const item = triaged;
18473
- if (!item || !item.route) return;
18474
- const topic2 = queueTopics.get(item.route);
18475
- if (topic2) topic2.publish(item);
18583
+ const routerInput = withLatestFrom(triageNode, triageInput);
18584
+ const router = effect([routerInput], ([pair]) => {
18585
+ const [classification, triagePair] = pair;
18586
+ if (!classification || !classification.route) return;
18587
+ const intakeItem = triagePair?.[0];
18588
+ const merged = { ...intakeItem, ...classification };
18589
+ const topic2 = queueTopics.get(merged.route);
18590
+ if (topic2) topic2.publish(merged);
18476
18591
  });
18477
18592
  const routerUnsub = router.subscribe(() => {
18478
18593
  });
@@ -18532,8 +18647,10 @@ function harnessLoop(name, opts) {
18532
18647
  executeInput
18533
18648
  );
18534
18649
  const maxReingestions = opts.maxReingestions ?? 1;
18535
- const retryTracker = /* @__PURE__ */ new Map();
18536
- const reingestionTracker = /* @__PURE__ */ new Map();
18650
+ const maxTotalRetries = Math.min(opts.maxTotalRetries ?? maxRetries * 10, 100);
18651
+ const maxTotalReingestions = Math.min(opts.maxTotalReingestions ?? maxReingestions * 10, 100);
18652
+ const totalRetries = state(0);
18653
+ const totalReingestions = state(0);
18537
18654
  const fastRetry = effect([verifyContext], ([ctx]) => {
18538
18655
  const [[vo, execRaw], item] = ctx;
18539
18656
  if (!vo || !item) return;
@@ -18559,29 +18676,33 @@ function harnessLoop(name, opts) {
18559
18676
  outcome: "failure",
18560
18677
  detail: vr.findings.join("; ")
18561
18678
  });
18562
- const key = baseSummary(item.summary);
18563
- const retryCount = retryTracker.get(key) ?? 0;
18564
- if (errClass === "self-correctable" && retryCount < maxRetries) {
18565
- retryTracker.set(key, retryCount + 1);
18679
+ const itemRetries = item._retries ?? 0;
18680
+ if (errClass === "self-correctable" && itemRetries < maxRetries && (totalRetries.get() ?? 0) < maxTotalRetries) {
18681
+ totalRetries.down([[DIRTY], [DATA, (totalRetries.get() ?? 0) + 1]]);
18682
+ const key = trackingKey(item);
18566
18683
  const retryItem = {
18567
18684
  ...item,
18568
- summary: `[RETRY ${retryCount + 1}/${maxRetries}] ${baseSummary(item.summary)} \u2014 Previous attempt failed: ${vr.findings.join("; ")}`
18685
+ _retries: itemRetries + 1,
18686
+ summary: `[RETRY ${itemRetries + 1}/${maxRetries}] ${key} \u2014 Previous attempt failed: ${vr.findings.join("; ")}`,
18687
+ relatedTo: [key]
18569
18688
  };
18570
18689
  retryTopic.publish(retryItem);
18571
18690
  } else {
18572
18691
  strategy.record(item.rootCause, item.intervention, false);
18573
18692
  verifyResults.publish(vr);
18574
- const itemReingestions = reingestionTracker.get(key) ?? 0;
18575
- if (itemReingestions < maxReingestions) {
18576
- reingestionTracker.set(key, itemReingestions + 1);
18693
+ const key = trackingKey(item);
18694
+ const itemReingestions = item._reingestions ?? 0;
18695
+ if (itemReingestions < maxReingestions && (totalReingestions.get() ?? 0) < maxTotalReingestions) {
18696
+ totalReingestions.down([[DIRTY], [DATA, (totalReingestions.get() ?? 0) + 1]]);
18577
18697
  intake.publish({
18578
18698
  source: "eval",
18579
- summary: `Verification failed for: ${baseSummary(item.summary)}`,
18699
+ summary: `Verification failed for: ${key}`,
18580
18700
  evidence: vr.findings.join("\n"),
18581
18701
  affectsAreas: item.affectsAreas,
18582
18702
  affectsEvalTasks: item.affectsEvalTasks,
18583
18703
  severity: "high",
18584
- relatedTo: [baseSummary(item.summary)]
18704
+ relatedTo: [key],
18705
+ _reingestions: itemReingestions + 1
18585
18706
  });
18586
18707
  }
18587
18708
  }
@@ -18595,12 +18716,16 @@ function harnessLoop(name, opts) {
18595
18716
  gateControllers,
18596
18717
  strategy,
18597
18718
  verifyResults,
18598
- retryTracker,
18599
- reingestionTracker
18719
+ totalRetries,
18720
+ totalReingestions
18600
18721
  );
18601
18722
  harness.addDisposer(routerUnsub);
18602
18723
  harness.addDisposer(fastRetryUnsub);
18603
18724
  harness.addDisposer(strategy.dispose);
18725
+ harness.add("triage", triageNode);
18726
+ harness.add("execute", executeNode);
18727
+ harness.add("verify", verifyNode);
18728
+ harness.add("strategy", strategy.node);
18604
18729
  harness.mount("intake", intake);
18605
18730
  for (const [route, topic2] of queueTopics) {
18606
18731
  harness.mount(`queue/${route}`, topic2);
@@ -18611,6 +18736,105 @@ function harnessLoop(name, opts) {
18611
18736
  return harness;
18612
18737
  }
18613
18738
 
18739
+ // src/patterns/harness/profile.ts
18740
+ function harnessProfile(harness, opts) {
18741
+ const base = graphProfile(harness, opts);
18742
+ const queueDepths = {};
18743
+ for (const [route, topic2] of harness.queues) {
18744
+ queueDepths[route] = topic2.retained().length;
18745
+ }
18746
+ return {
18747
+ ...base,
18748
+ queueDepths,
18749
+ strategyEntries: harness.strategy.node.get()?.size ?? 0,
18750
+ totalRetries: harness.totalRetries.get() ?? 0,
18751
+ totalReingestions: harness.totalReingestions.get() ?? 0
18752
+ };
18753
+ }
18754
+
18755
+ // src/patterns/harness/trace.ts
18756
+ var STAGE_LABELS = {
18757
+ "intake::latest": "INTAKE",
18758
+ triage: "TRIAGE",
18759
+ execute: "EXECUTE",
18760
+ "verify-results::latest": "VERIFY",
18761
+ strategy: "STRATEGY"
18762
+ };
18763
+ for (const route of QUEUE_NAMES) {
18764
+ STAGE_LABELS[`queue/${route}::latest`] = "QUEUE";
18765
+ }
18766
+ function harnessTrace(harness, opts) {
18767
+ const logger = opts?.logger ?? console.log;
18768
+ const startNs = monotonicNs();
18769
+ const observations = [];
18770
+ function elapsed() {
18771
+ const deltaNs = monotonicNs() - startNs;
18772
+ const secs = deltaNs / 1e9;
18773
+ return secs.toFixed(3);
18774
+ }
18775
+ for (const [path, stage] of Object.entries(STAGE_LABELS)) {
18776
+ try {
18777
+ const obs = harness.observe(path, {
18778
+ format: "json",
18779
+ logger: (_line, event) => {
18780
+ if (event.type === "data") {
18781
+ const dataStr = event.data !== void 0 ? ` ${summarize(event.data)}` : "";
18782
+ logger(`[${elapsed()}s] ${stage.padEnd(9)} \u2190${dataStr}`);
18783
+ } else if (event.type === "error") {
18784
+ const errStr = event.data !== void 0 ? ` ${summarize(event.data)}` : "";
18785
+ logger(`[${elapsed()}s] ${stage.padEnd(9)} \u2717${errStr}`);
18786
+ } else if (event.type === "complete") {
18787
+ logger(`[${elapsed()}s] ${stage.padEnd(9)} \u25A0 complete`);
18788
+ }
18789
+ },
18790
+ includeTypes: ["data", "error", "complete"]
18791
+ });
18792
+ observations.push(obs);
18793
+ } catch {
18794
+ }
18795
+ }
18796
+ for (const [gatedRoute] of harness.gates) {
18797
+ const gatePath = `gates::${gatedRoute}/gate`;
18798
+ try {
18799
+ const obs = harness.observe(gatePath, {
18800
+ format: "json",
18801
+ logger: (_line, event) => {
18802
+ if (event.type === "data") {
18803
+ const dataStr = event.data !== void 0 ? ` ${summarize(event.data)}` : "";
18804
+ logger(`[${elapsed()}s] GATE \u25B6${dataStr}`);
18805
+ } else if (event.type === "error") {
18806
+ logger(`[${elapsed()}s] GATE \u2717 ${summarize(event.data)}`);
18807
+ }
18808
+ },
18809
+ includeTypes: ["data", "error", "complete"]
18810
+ });
18811
+ observations.push(obs);
18812
+ } catch {
18813
+ }
18814
+ }
18815
+ return {
18816
+ dispose() {
18817
+ for (const obs of observations) obs.dispose();
18818
+ observations.length = 0;
18819
+ }
18820
+ };
18821
+ }
18822
+ function summarize(value) {
18823
+ if (value == null) return "null";
18824
+ if (typeof value === "string") return truncate(value, 80);
18825
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
18826
+ if (typeof value === "bigint") return String(value);
18827
+ try {
18828
+ const json = JSON.stringify(value);
18829
+ return truncate(json, 120);
18830
+ } catch {
18831
+ return String(value);
18832
+ }
18833
+ }
18834
+ function truncate(s, max) {
18835
+ return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
18836
+ }
18837
+
18614
18838
  // src/patterns/reactive-layout/index.ts
18615
18839
  var reactive_layout_exports = {};
18616
18840
  __export(reactive_layout_exports, {
@@ -19169,7 +19393,6 @@ var version = "0.0.0";
19169
19393
  delay,
19170
19394
  demoShell,
19171
19395
  derived,
19172
- describeNode,
19173
19396
  deserializeError,
19174
19397
  distill,
19175
19398
  distinctUntilChanged,
@@ -19224,6 +19447,7 @@ var version = "0.0.0";
19224
19447
  fromWebhook,
19225
19448
  globToRegExp,
19226
19449
  graph,
19450
+ graphProfile,
19227
19451
  graphspec,
19228
19452
  harness,
19229
19453
  interval,
@@ -19247,7 +19471,6 @@ var version = "0.0.0";
19247
19471
  mergeMap,
19248
19472
  messageTier,
19249
19473
  messaging,
19250
- metaSnapshot,
19251
19474
  monotonicNs,
19252
19475
  nameToSignal,
19253
19476
  nanostores,
@@ -19256,8 +19479,6 @@ var version = "0.0.0";
19256
19479
  never,
19257
19480
  node,
19258
19481
  normalizeActor,
19259
- observeGraph$,
19260
- observeNode$,
19261
19482
  of,
19262
19483
  orchestration,
19263
19484
  pairwise,
@@ -19302,6 +19523,7 @@ var version = "0.0.0";
19302
19523
  shareReplay,
19303
19524
  signalToName,
19304
19525
  signals,
19526
+ sizeof,
19305
19527
  skip,
19306
19528
  solid,
19307
19529
  startWith,
@@ -19323,7 +19545,6 @@ var version = "0.0.0";
19323
19545
  toFile,
19324
19546
  toKafka,
19325
19547
  toLoki,
19326
- toMessages$,
19327
19548
  toMongo,
19328
19549
  toNATS,
19329
19550
  toObservable,