@probelabs/visor 0.1.186-ee → 0.1.187-ee

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 (194) hide show
  1. package/defaults/assistant.yaml +31 -0
  2. package/defaults/code-talk.yaml +32 -0
  3. package/defaults/skills/code-explorer.yaml +6 -0
  4. package/dist/agent-protocol/task-live-update-slack.d.ts +10 -0
  5. package/dist/agent-protocol/task-live-update-slack.d.ts.map +1 -1
  6. package/dist/agent-protocol/task-live-updates.d.ts +10 -0
  7. package/dist/agent-protocol/task-live-updates.d.ts.map +1 -1
  8. package/dist/agent-protocol/tasks-cli-handler.d.ts.map +1 -1
  9. package/dist/agent-protocol/trace-serializer.d.ts +43 -1
  10. package/dist/agent-protocol/trace-serializer.d.ts.map +1 -1
  11. package/dist/agent-protocol/track-execution.d.ts.map +1 -1
  12. package/dist/ai-review-service.d.ts +22 -1
  13. package/dist/ai-review-service.d.ts.map +1 -1
  14. package/dist/cli-main.d.ts +1 -0
  15. package/dist/cli-main.d.ts.map +1 -1
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/defaults/assistant.yaml +31 -0
  18. package/dist/defaults/code-talk.yaml +32 -0
  19. package/dist/defaults/skills/code-explorer.yaml +6 -0
  20. package/dist/docs/telemetry-setup.md +18 -2
  21. package/dist/email/polling-runner.d.ts +1 -0
  22. package/dist/email/polling-runner.d.ts.map +1 -1
  23. package/dist/frontends/email-frontend.d.ts.map +1 -1
  24. package/dist/frontends/slack-frontend.d.ts.map +1 -1
  25. package/dist/frontends/teams-frontend.d.ts.map +1 -1
  26. package/dist/frontends/telegram-frontend.d.ts.map +1 -1
  27. package/dist/frontends/whatsapp-frontend.d.ts.map +1 -1
  28. package/dist/generated/config-schema.d.ts +16 -8
  29. package/dist/generated/config-schema.d.ts.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +7658 -1460
  33. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  34. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  35. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
  36. package/dist/providers/script-check-provider.d.ts.map +1 -1
  37. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  38. package/dist/runners/mcp-server-runner.d.ts.map +1 -1
  39. package/dist/scheduler/scheduler.d.ts.map +1 -1
  40. package/dist/sdk/a2a-frontend-7EGXSULE.mjs +1751 -0
  41. package/dist/sdk/a2a-frontend-7EGXSULE.mjs.map +1 -0
  42. package/dist/sdk/{a2a-frontend-OI4OVSKC.mjs → a2a-frontend-QVKJ7MVW.mjs} +3 -3
  43. package/dist/sdk/{check-provider-registry-TQR32QBD.mjs → check-provider-registry-IGNTM4MW.mjs} +5 -5
  44. package/dist/sdk/{check-provider-registry-7T2AEWLU.mjs → check-provider-registry-QUUL6JI2.mjs} +14 -11
  45. package/dist/sdk/chunk-2LLKENYD.mjs +33 -0
  46. package/dist/sdk/chunk-2LLKENYD.mjs.map +1 -0
  47. package/dist/sdk/{chunk-XX6WT332.mjs → chunk-6DDNEBZ7.mjs} +2 -1
  48. package/dist/sdk/{chunk-XX6WT332.mjs.map → chunk-6DDNEBZ7.mjs.map} +1 -1
  49. package/dist/sdk/chunk-6LQEODDA.mjs +391 -0
  50. package/dist/sdk/chunk-6LQEODDA.mjs.map +1 -0
  51. package/dist/sdk/chunk-77AKSSW2.mjs +175 -0
  52. package/dist/sdk/chunk-77AKSSW2.mjs.map +1 -0
  53. package/dist/sdk/chunk-7QI6F66G.mjs +145 -0
  54. package/dist/sdk/chunk-7QI6F66G.mjs.map +1 -0
  55. package/dist/sdk/{chunk-UM7LGO2P.mjs → chunk-BBLBZVWC.mjs} +3 -3
  56. package/dist/sdk/chunk-BVEATT5V.mjs +2495 -0
  57. package/dist/sdk/chunk-BVEATT5V.mjs.map +1 -0
  58. package/dist/sdk/{chunk-SRU5TFNY.mjs → chunk-D6O5SCPC.mjs} +2 -1
  59. package/dist/sdk/{chunk-SRU5TFNY.mjs.map → chunk-D6O5SCPC.mjs.map} +1 -1
  60. package/dist/sdk/chunk-H2ZWNJJO.mjs +204 -0
  61. package/dist/sdk/chunk-H2ZWNJJO.mjs.map +1 -0
  62. package/dist/sdk/{chunk-TAOGXCWT.mjs → chunk-HMVD3AEC.mjs} +16 -16
  63. package/dist/sdk/{chunk-LWH6CVLZ.mjs → chunk-HQCCT6WP.mjs} +570 -259
  64. package/dist/sdk/chunk-HQCCT6WP.mjs.map +1 -0
  65. package/dist/sdk/chunk-HW4MPCOW.mjs +691 -0
  66. package/dist/sdk/chunk-HW4MPCOW.mjs.map +1 -0
  67. package/dist/sdk/chunk-PGBV3VZB.mjs +122 -0
  68. package/dist/sdk/chunk-PGBV3VZB.mjs.map +1 -0
  69. package/dist/sdk/chunk-PZADRRLX.mjs +739 -0
  70. package/dist/sdk/chunk-PZADRRLX.mjs.map +1 -0
  71. package/dist/sdk/chunk-QT766ZLD.mjs +217 -0
  72. package/dist/sdk/chunk-QT766ZLD.mjs.map +1 -0
  73. package/dist/sdk/chunk-RQDLVMER.mjs +1507 -0
  74. package/dist/sdk/chunk-RQDLVMER.mjs.map +1 -0
  75. package/dist/sdk/chunk-TL3ZTYFY.mjs +141 -0
  76. package/dist/sdk/chunk-TL3ZTYFY.mjs.map +1 -0
  77. package/dist/sdk/{chunk-YBXNG75V.mjs → chunk-YTG5DN72.mjs} +103 -28
  78. package/dist/sdk/chunk-YTG5DN72.mjs.map +1 -0
  79. package/dist/sdk/chunk-YU3VR5SZ.mjs +749 -0
  80. package/dist/sdk/chunk-YU3VR5SZ.mjs.map +1 -0
  81. package/dist/sdk/chunk-ZCBVXBKG.mjs +1150 -0
  82. package/dist/sdk/chunk-ZCBVXBKG.mjs.map +1 -0
  83. package/dist/sdk/{config-BCYAVJ5S.mjs → config-BI5ZXG6D.mjs} +2 -2
  84. package/dist/sdk/{config-TVU5RWR5.mjs → config-H5IOLBFA.mjs} +2 -2
  85. package/dist/sdk/{dist-PN5UHL6A.mjs → dist-YLO6HUFD.mjs} +238 -65
  86. package/dist/sdk/dist-YLO6HUFD.mjs.map +1 -0
  87. package/dist/sdk/{email-frontend-6JU4L33L.mjs → email-frontend-6O454VL5.mjs} +18 -3
  88. package/dist/sdk/{email-frontend-ECHQCFTR.mjs.map → email-frontend-6O454VL5.mjs.map} +1 -1
  89. package/dist/sdk/{email-frontend-ECHQCFTR.mjs → email-frontend-JE7H3LBC.mjs} +2 -2
  90. package/dist/sdk/failure-condition-evaluator-7WHZUYDC.mjs +18 -0
  91. package/dist/sdk/github-frontend-RGK4DPRI.mjs +1394 -0
  92. package/dist/sdk/github-frontend-RGK4DPRI.mjs.map +1 -0
  93. package/dist/sdk/{host-RM6UJEPP.mjs → host-UZESVA6Z.mjs} +8 -8
  94. package/dist/sdk/{host-OJSMCLKK.mjs → host-YWXWROIE.mjs} +6 -6
  95. package/dist/sdk/oauth2-token-cache-OS7WHLDI.mjs +13 -0
  96. package/dist/sdk/{routing-NNQQSLWA.mjs → routing-PHHRW2C7.mjs} +2 -2
  97. package/dist/sdk/routing-TYXT3STD.mjs +26 -0
  98. package/dist/sdk/{schedule-tool-7IQI6MID.mjs → schedule-tool-ITD445EO.mjs} +5 -5
  99. package/dist/sdk/{schedule-tool-25C5NMDG.mjs → schedule-tool-ODMIDBMT.mjs} +14 -11
  100. package/dist/sdk/{schedule-tool-handler-IYBNJLTV.mjs → schedule-tool-handler-5WPHFBOG.mjs} +5 -5
  101. package/dist/sdk/{schedule-tool-handler-VWGTVSB6.mjs → schedule-tool-handler-IQSKBFLS.mjs} +14 -11
  102. package/dist/sdk/schedule-tool-handler-IQSKBFLS.mjs.map +1 -0
  103. package/dist/sdk/sdk.d.mts +14 -2
  104. package/dist/sdk/sdk.d.ts +14 -2
  105. package/dist/sdk/sdk.js +1926 -642
  106. package/dist/sdk/sdk.js.map +1 -1
  107. package/dist/sdk/sdk.mjs +13 -10
  108. package/dist/sdk/sdk.mjs.map +1 -1
  109. package/dist/sdk/session-registry-CENXWIFR.mjs +12 -0
  110. package/dist/sdk/session-registry-CENXWIFR.mjs.map +1 -0
  111. package/dist/sdk/{slack-frontend-K3TPGERM.mjs → slack-frontend-H7PX5GE7.mjs} +2 -2
  112. package/dist/sdk/slack-frontend-JMX5MUVZ.mjs +1015 -0
  113. package/dist/sdk/slack-frontend-JMX5MUVZ.mjs.map +1 -0
  114. package/dist/sdk/task-evaluator-4QG4CYQA.mjs +264 -0
  115. package/dist/sdk/task-evaluator-4QG4CYQA.mjs.map +1 -0
  116. package/dist/sdk/teams-frontend-6MDAN7OR.mjs +355 -0
  117. package/dist/sdk/teams-frontend-6MDAN7OR.mjs.map +1 -0
  118. package/dist/sdk/{teams-frontend-6RRW533K.mjs → teams-frontend-HCT4MTY4.mjs} +2 -2
  119. package/dist/sdk/telegram-frontend-NLX2ZHS4.mjs +599 -0
  120. package/dist/sdk/telegram-frontend-NLX2ZHS4.mjs.map +1 -0
  121. package/dist/sdk/{telegram-frontend-5UA77YAT.mjs → telegram-frontend-YQRYDKPN.mjs} +2 -2
  122. package/dist/sdk/trace-helpers-AM2QE5UZ.mjs +31 -0
  123. package/dist/sdk/trace-helpers-AM2QE5UZ.mjs.map +1 -0
  124. package/dist/sdk/trace-serializer-4TOIAVQL.mjs +32 -0
  125. package/dist/sdk/trace-serializer-4TOIAVQL.mjs.map +1 -0
  126. package/dist/sdk/{track-execution-3CHMGEPH.mjs → track-execution-BULXL2XD.mjs} +2 -2
  127. package/dist/sdk/track-execution-VJJVJH6K.mjs +320 -0
  128. package/dist/sdk/track-execution-VJJVJH6K.mjs.map +1 -0
  129. package/dist/sdk/utcp-check-provider-WDTSQ7DZ.mjs +17 -0
  130. package/dist/sdk/utcp-check-provider-WDTSQ7DZ.mjs.map +1 -0
  131. package/dist/sdk/whatsapp-frontend-3EMMNC7R.mjs +451 -0
  132. package/dist/sdk/whatsapp-frontend-3EMMNC7R.mjs.map +1 -0
  133. package/dist/sdk/{workflow-check-provider-FOWDJUO3.mjs → workflow-check-provider-OVZDCL4E.mjs} +5 -5
  134. package/dist/sdk/workflow-check-provider-OVZDCL4E.mjs.map +1 -0
  135. package/dist/sdk/{workflow-check-provider-MRP3C2NC.mjs → workflow-check-provider-XOWQYWTC.mjs} +14 -11
  136. package/dist/sdk/workflow-check-provider-XOWQYWTC.mjs.map +1 -0
  137. package/dist/session-registry.d.ts +2 -7
  138. package/dist/session-registry.d.ts.map +1 -1
  139. package/dist/slack/client.d.ts +8 -0
  140. package/dist/slack/client.d.ts.map +1 -1
  141. package/dist/slack/markdown.d.ts.map +1 -1
  142. package/dist/slack/slack-output-adapter.d.ts.map +1 -1
  143. package/dist/slack/socket-runner.d.ts +1 -0
  144. package/dist/slack/socket-runner.d.ts.map +1 -1
  145. package/dist/state-machine/dispatch/debounce-manager.d.ts +44 -0
  146. package/dist/state-machine/dispatch/debounce-manager.d.ts.map +1 -0
  147. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
  148. package/dist/state-machine-execution-engine.d.ts +1 -0
  149. package/dist/state-machine-execution-engine.d.ts.map +1 -1
  150. package/dist/teams/webhook-runner.d.ts +1 -0
  151. package/dist/teams/webhook-runner.d.ts.map +1 -1
  152. package/dist/telegram/polling-runner.d.ts +1 -0
  153. package/dist/telegram/polling-runner.d.ts.map +1 -1
  154. package/dist/types/config.d.ts +14 -2
  155. package/dist/types/config.d.ts.map +1 -1
  156. package/dist/utils/child-process-error-handler.d.ts +19 -0
  157. package/dist/utils/child-process-error-handler.d.ts.map +1 -0
  158. package/dist/utils/user-facing-error.d.ts +4 -0
  159. package/dist/utils/user-facing-error.d.ts.map +1 -0
  160. package/dist/utils/workspace-manager.d.ts +5 -0
  161. package/dist/utils/workspace-manager.d.ts.map +1 -1
  162. package/dist/utils/worktree-cleanup.d.ts +28 -0
  163. package/dist/utils/worktree-cleanup.d.ts.map +1 -1
  164. package/dist/utils/worktree-manager.d.ts +6 -0
  165. package/dist/utils/worktree-manager.d.ts.map +1 -1
  166. package/dist/whatsapp/webhook-runner.d.ts +1 -0
  167. package/dist/whatsapp/webhook-runner.d.ts.map +1 -1
  168. package/dist/workflow-executor.d.ts +7 -0
  169. package/dist/workflow-executor.d.ts.map +1 -1
  170. package/package.json +3 -3
  171. package/dist/sdk/chunk-LWH6CVLZ.mjs.map +0 -1
  172. package/dist/sdk/chunk-YBXNG75V.mjs.map +0 -1
  173. package/dist/sdk/dist-PN5UHL6A.mjs.map +0 -1
  174. /package/dist/sdk/{a2a-frontend-OI4OVSKC.mjs.map → a2a-frontend-QVKJ7MVW.mjs.map} +0 -0
  175. /package/dist/sdk/{check-provider-registry-7T2AEWLU.mjs.map → check-provider-registry-IGNTM4MW.mjs.map} +0 -0
  176. /package/dist/sdk/{check-provider-registry-TQR32QBD.mjs.map → check-provider-registry-QUUL6JI2.mjs.map} +0 -0
  177. /package/dist/sdk/{chunk-UM7LGO2P.mjs.map → chunk-BBLBZVWC.mjs.map} +0 -0
  178. /package/dist/sdk/{chunk-TAOGXCWT.mjs.map → chunk-HMVD3AEC.mjs.map} +0 -0
  179. /package/dist/sdk/{config-BCYAVJ5S.mjs.map → config-BI5ZXG6D.mjs.map} +0 -0
  180. /package/dist/sdk/{config-TVU5RWR5.mjs.map → config-H5IOLBFA.mjs.map} +0 -0
  181. /package/dist/sdk/{email-frontend-6JU4L33L.mjs.map → email-frontend-JE7H3LBC.mjs.map} +0 -0
  182. /package/dist/sdk/{routing-NNQQSLWA.mjs.map → failure-condition-evaluator-7WHZUYDC.mjs.map} +0 -0
  183. /package/dist/sdk/{host-OJSMCLKK.mjs.map → host-UZESVA6Z.mjs.map} +0 -0
  184. /package/dist/sdk/{host-RM6UJEPP.mjs.map → host-YWXWROIE.mjs.map} +0 -0
  185. /package/dist/sdk/{schedule-tool-25C5NMDG.mjs.map → oauth2-token-cache-OS7WHLDI.mjs.map} +0 -0
  186. /package/dist/sdk/{schedule-tool-7IQI6MID.mjs.map → routing-PHHRW2C7.mjs.map} +0 -0
  187. /package/dist/sdk/{schedule-tool-handler-IYBNJLTV.mjs.map → routing-TYXT3STD.mjs.map} +0 -0
  188. /package/dist/sdk/{schedule-tool-handler-VWGTVSB6.mjs.map → schedule-tool-ITD445EO.mjs.map} +0 -0
  189. /package/dist/sdk/{workflow-check-provider-FOWDJUO3.mjs.map → schedule-tool-ODMIDBMT.mjs.map} +0 -0
  190. /package/dist/sdk/{workflow-check-provider-MRP3C2NC.mjs.map → schedule-tool-handler-5WPHFBOG.mjs.map} +0 -0
  191. /package/dist/sdk/{slack-frontend-K3TPGERM.mjs.map → slack-frontend-H7PX5GE7.mjs.map} +0 -0
  192. /package/dist/sdk/{teams-frontend-6RRW533K.mjs.map → teams-frontend-HCT4MTY4.mjs.map} +0 -0
  193. /package/dist/sdk/{telegram-frontend-5UA77YAT.mjs.map → telegram-frontend-YQRYDKPN.mjs.map} +0 -0
  194. /package/dist/sdk/{track-execution-3CHMGEPH.mjs.map → track-execution-BULXL2XD.mjs.map} +0 -0
@@ -0,0 +1,1507 @@
1
+ import {
2
+ FailureConditionEvaluator,
3
+ init_failure_condition_evaluator
4
+ } from "./chunk-7XKHFRPN.mjs";
5
+ import {
6
+ addEvent,
7
+ init_trace_helpers
8
+ } from "./chunk-QLT42TX7.mjs";
9
+ import {
10
+ createExtendedLiquid,
11
+ init_liquid_extensions
12
+ } from "./chunk-4HIWZA6M.mjs";
13
+ import {
14
+ compileAndRun,
15
+ createSecureSandbox,
16
+ init_sandbox
17
+ } from "./chunk-LW3INISN.mjs";
18
+ import {
19
+ MemoryStore,
20
+ init_memory_store
21
+ } from "./chunk-4MHHELVZ.mjs";
22
+ import {
23
+ init_logger,
24
+ logger
25
+ } from "./chunk-6E625R3C.mjs";
26
+ import {
27
+ __esm,
28
+ __export,
29
+ __toCommonJS
30
+ } from "./chunk-J7LXIPZS.mjs";
31
+
32
+ // src/snapshot-store.ts
33
+ var snapshot_store_exports = {};
34
+ __export(snapshot_store_exports, {
35
+ ContextView: () => ContextView,
36
+ ExecutionJournal: () => ExecutionJournal
37
+ });
38
+ var ExecutionJournal, ContextView;
39
+ var init_snapshot_store = __esm({
40
+ "src/snapshot-store.ts"() {
41
+ "use strict";
42
+ ExecutionJournal = class {
43
+ commit = 0;
44
+ entries = [];
45
+ beginSnapshot() {
46
+ return this.commit;
47
+ }
48
+ commitEntry(entry) {
49
+ const committed = {
50
+ sessionId: entry.sessionId,
51
+ scope: entry.scope,
52
+ checkId: entry.checkId,
53
+ result: entry.result,
54
+ event: entry.event,
55
+ commitId: ++this.commit
56
+ };
57
+ this.entries.push(committed);
58
+ return committed;
59
+ }
60
+ readVisible(sessionId, commitMax, event) {
61
+ return this.entries.filter(
62
+ (e) => e.sessionId === sessionId && e.commitId <= commitMax && (event ? e.event === event : true)
63
+ );
64
+ }
65
+ // Lightweight helpers for debugging/metrics
66
+ size() {
67
+ return this.entries.length;
68
+ }
69
+ };
70
+ ContextView = class {
71
+ constructor(journal, sessionId, snapshotId, scope, event) {
72
+ this.journal = journal;
73
+ this.sessionId = sessionId;
74
+ this.snapshotId = snapshotId;
75
+ this.scope = scope;
76
+ this.event = event;
77
+ }
78
+ journal;
79
+ sessionId;
80
+ snapshotId;
81
+ scope;
82
+ event;
83
+ /** Return the nearest result for a check in this scope (exact item → ancestor → latest). */
84
+ get(checkId) {
85
+ const visible = this.journal.readVisible(this.sessionId, this.snapshotId, this.event).filter((e) => e.checkId === checkId);
86
+ if (visible.length === 0) return void 0;
87
+ const exactMatches = visible.filter((e) => this.sameScope(e.scope, this.scope));
88
+ if (exactMatches.length > 0) {
89
+ return exactMatches[exactMatches.length - 1].result;
90
+ }
91
+ let best;
92
+ for (const e of visible) {
93
+ const dist = this.ancestorDistance(e.scope, this.scope);
94
+ if (dist >= 0 && (best === void 0 || dist < best.dist)) {
95
+ best = { entry: e, dist };
96
+ }
97
+ }
98
+ if (best) return best.entry.result;
99
+ return visible[visible.length - 1]?.result;
100
+ }
101
+ /** Return an aggregate (raw) result – the shallowest scope for this check. */
102
+ getRaw(checkId) {
103
+ const visible = this.journal.readVisible(this.sessionId, this.snapshotId, this.event).filter((e) => e.checkId === checkId);
104
+ if (visible.length === 0) return void 0;
105
+ let shallow = visible[0];
106
+ for (const e of visible) {
107
+ if (e.scope.length < shallow.scope.length) shallow = e;
108
+ }
109
+ return shallow.result;
110
+ }
111
+ /** All results for a check up to this snapshot. */
112
+ getHistory(checkId) {
113
+ return this.journal.readVisible(this.sessionId, this.snapshotId, this.event).filter((e) => e.checkId === checkId).map((e) => e.result);
114
+ }
115
+ sameScope(a, b) {
116
+ if (a.length !== b.length) return false;
117
+ for (let i = 0; i < a.length; i++) {
118
+ if (a[i].check !== b[i].check || a[i].index !== b[i].index) return false;
119
+ }
120
+ return true;
121
+ }
122
+ // distance from ancestor to current; -1 if not ancestor
123
+ ancestorDistance(ancestor, current) {
124
+ if (ancestor.length > current.length) return -1;
125
+ if (ancestor.length === 0 && current.length > 0) return -1;
126
+ for (let i = 0; i < ancestor.length; i++) {
127
+ if (ancestor[i].check !== current[i].check || ancestor[i].index !== current[i].index)
128
+ return -1;
129
+ }
130
+ return current.length - ancestor.length;
131
+ }
132
+ };
133
+ }
134
+ });
135
+
136
+ // src/state-machine/states/routing.ts
137
+ async function renderRouteArgs(args, output, dependencyResults, context) {
138
+ if (!args || Object.keys(args).length === 0) {
139
+ return args;
140
+ }
141
+ const liquid = createExtendedLiquid();
142
+ const renderedArgs = {};
143
+ const templateContext = {
144
+ output,
145
+ // Output of the step that triggered routing
146
+ outputs: dependencyResults,
147
+ // All dependency outputs
148
+ env: process.env,
149
+ inputs: context.executionContext?.workflowInputs || {}
150
+ };
151
+ for (const [key, value] of Object.entries(args)) {
152
+ if (typeof value === "string" && value.includes("{{")) {
153
+ try {
154
+ renderedArgs[key] = await liquid.parseAndRender(value, templateContext);
155
+ } catch (error) {
156
+ logger.warn(`[Routing] Failed to render template for arg ${key}: ${error}`);
157
+ renderedArgs[key] = value;
158
+ }
159
+ } else {
160
+ renderedArgs[key] = value;
161
+ }
162
+ }
163
+ return renderedArgs;
164
+ }
165
+ function parseRunItem(item) {
166
+ if (typeof item === "string") {
167
+ return { target: item };
168
+ }
169
+ if ("step" in item) {
170
+ const stepItem = item;
171
+ return { target: stepItem.step, args: stepItem.with };
172
+ }
173
+ if ("workflow" in item) {
174
+ const workflowItem = item;
175
+ return { target: workflowItem.workflow, args: workflowItem.with };
176
+ }
177
+ return { target: String(item) };
178
+ }
179
+ function hasMapFanoutDependents(context, checkId) {
180
+ const checks = context.config.checks || {};
181
+ const reduceProviders = /* @__PURE__ */ new Set(["log", "memory", "script", "workflow", "noop"]);
182
+ for (const [cid, cfg] of Object.entries(checks)) {
183
+ if (cid === checkId) continue;
184
+ const rawDeps = cfg.depends_on || [];
185
+ const depList = Array.isArray(rawDeps) ? rawDeps : [rawDeps];
186
+ let depends = false;
187
+ for (const dep of depList) {
188
+ if (typeof dep !== "string") continue;
189
+ if (dep.includes("|")) {
190
+ const opts = dep.split("|").map((s) => s.trim()).filter(Boolean);
191
+ if (opts.includes(checkId)) {
192
+ depends = true;
193
+ break;
194
+ }
195
+ } else if (dep === checkId) {
196
+ depends = true;
197
+ break;
198
+ }
199
+ }
200
+ if (!depends) continue;
201
+ const explicit = cfg.fanout;
202
+ if (explicit === "map") return true;
203
+ if (explicit === "reduce") continue;
204
+ const providerType = context.checks[cid]?.providerType || checks[cid]?.type || "";
205
+ const inferred = reduceProviders.has(providerType) ? "reduce" : "map";
206
+ if (inferred === "map") return true;
207
+ }
208
+ return false;
209
+ }
210
+ function classifyFailure(result) {
211
+ const issues = result?.issues || [];
212
+ if (!issues || issues.length === 0) return "none";
213
+ let hasLogical = false;
214
+ let hasExecution = false;
215
+ for (const iss of issues) {
216
+ const id = String(iss.ruleId || "");
217
+ const msg = String(iss.message || "");
218
+ const msgLower = msg.toLowerCase();
219
+ if (id.endsWith("_fail_if") || id.includes("contract/guarantee_failed") || id.includes("contract/schema_validation_failed"))
220
+ hasLogical = true;
221
+ if (id.endsWith("/error") || id.includes("/execution_error") || id.includes("timeout") || msgLower.includes("timed out") || msg.includes("Command execution failed"))
222
+ hasExecution = true;
223
+ if (id.includes("forEach/execution_error") || msg.includes("sandbox_runner_error"))
224
+ hasExecution = true;
225
+ }
226
+ if (hasLogical && !hasExecution) return "logical";
227
+ if (hasExecution && !hasLogical) return "execution";
228
+ return hasExecution ? "execution" : "logical";
229
+ }
230
+ function getCriticality(context, checkId) {
231
+ const cfg = context.config.checks?.[checkId];
232
+ return cfg && cfg.criticality || "policy";
233
+ }
234
+ function createMemoryHelpers() {
235
+ const memoryStore = MemoryStore.getInstance();
236
+ return {
237
+ get: (key, ns) => memoryStore.get(key, ns),
238
+ has: (key, ns) => memoryStore.has(key, ns),
239
+ getAll: (ns) => memoryStore.getAll(ns),
240
+ set: (key, value, ns) => {
241
+ const nsName = ns || memoryStore.getDefaultNamespace();
242
+ const data = memoryStore["data"];
243
+ if (!data.has(nsName)) data.set(nsName, /* @__PURE__ */ new Map());
244
+ data.get(nsName).set(key, value);
245
+ },
246
+ clear: (ns) => {
247
+ const data = memoryStore["data"];
248
+ if (ns) data.delete(ns);
249
+ else data.clear();
250
+ },
251
+ increment: (key, amount = 1, ns) => {
252
+ const nsName = ns || memoryStore.getDefaultNamespace();
253
+ const data = memoryStore["data"];
254
+ if (!data.has(nsName)) data.set(nsName, /* @__PURE__ */ new Map());
255
+ const nsMap = data.get(nsName);
256
+ const current = nsMap.get(key);
257
+ const numCurrent = typeof current === "number" ? current : 0;
258
+ const newValue = numCurrent + amount;
259
+ nsMap.set(key, newValue);
260
+ return newValue;
261
+ }
262
+ };
263
+ }
264
+ function getHistoryLimit() {
265
+ const raw = process.env.VISOR_TEST_HISTORY_LIMIT || process.env.VISOR_OUTPUT_HISTORY_LIMIT;
266
+ if (!raw) return void 0;
267
+ const n = parseInt(raw, 10);
268
+ return Number.isFinite(n) && n > 0 ? n : void 0;
269
+ }
270
+ function formatScopeLabel(scope) {
271
+ if (!scope || scope.length === 0) return "";
272
+ return scope.map((item) => `${item.check}:${item.index}`).join("|");
273
+ }
274
+ function recordRoutingEvent(args) {
275
+ const attrs = {
276
+ check_id: args.checkId,
277
+ trigger: args.trigger,
278
+ action: args.action
279
+ };
280
+ if (args.target) attrs.target = args.target;
281
+ if (args.source) attrs.source = args.source;
282
+ const scopeLabel = formatScopeLabel(args.scope);
283
+ if (scopeLabel) attrs.scope = scopeLabel;
284
+ if (args.gotoEvent) attrs.goto_event = args.gotoEvent;
285
+ addEvent("visor.routing", attrs);
286
+ }
287
+ async function handleRouting(context, state, transition, emitEvent, routingContext) {
288
+ const { checkId, scope, result, checkConfig, success } = routingContext;
289
+ logger.info(`[Routing] Evaluating routing for check: ${checkId}, success: ${success}`);
290
+ const failureResult = await evaluateFailIf(checkId, result, checkConfig, context, state);
291
+ if (failureResult.haltExecution) {
292
+ logger.error(
293
+ `[Routing] HALTING EXECUTION due to critical failure in ${checkId}: ${failureResult.haltMessage}`
294
+ );
295
+ const haltIssue = {
296
+ file: "system",
297
+ line: 0,
298
+ ruleId: `${checkId}_halt_execution`,
299
+ message: `Execution halted: ${failureResult.haltMessage || "Critical failure condition met"}`,
300
+ severity: "error",
301
+ category: "logic"
302
+ };
303
+ result.issues = [...result.issues || [], haltIssue];
304
+ emitEvent({
305
+ type: "Shutdown",
306
+ error: {
307
+ message: failureResult.haltMessage || `Execution halted by check ${checkId}`,
308
+ name: "HaltExecution"
309
+ }
310
+ });
311
+ transition("Error");
312
+ return true;
313
+ }
314
+ if (failureResult.failed) {
315
+ if (context.debug) {
316
+ logger.info(`[Routing] fail_if/failure_conditions triggered for ${checkId}`);
317
+ }
318
+ await processOnFail(checkId, scope, result, checkConfig, context, state, emitEvent);
319
+ } else if (success) {
320
+ await processOnSuccess(checkId, scope, result, checkConfig, context, state, emitEvent);
321
+ } else {
322
+ await processOnFail(checkId, scope, result, checkConfig, context, state, emitEvent);
323
+ }
324
+ const shouldProcessOnFinishHere = !!checkConfig.on_finish && (checkConfig.forEach !== true || !hasMapFanoutDependents(context, checkId));
325
+ if (checkConfig.on_finish) {
326
+ logger.info(
327
+ `[Routing] on_finish decision for ${checkId}: forEach=${!!checkConfig.forEach}, processHere=${shouldProcessOnFinishHere}`
328
+ );
329
+ }
330
+ if (shouldProcessOnFinishHere) {
331
+ await processOnFinish(checkId, scope, result, checkConfig, context, state, emitEvent);
332
+ }
333
+ transition("WavePlanning");
334
+ return false;
335
+ }
336
+ async function processOnFinish(checkId, scope, result, checkConfig, context, state, emitEvent) {
337
+ const onFinish = checkConfig.on_finish;
338
+ if (!onFinish) {
339
+ return;
340
+ }
341
+ logger.info(`Processing on_finish for ${checkId}`);
342
+ let queuedForward = false;
343
+ if (onFinish.run && onFinish.run.length > 0) {
344
+ const currentCheckIsForEach = checkConfig.forEach === true;
345
+ const forEachItems = currentCheckIsForEach ? result.forEachItems : void 0;
346
+ const hasForEachItems = Array.isArray(forEachItems) && forEachItems.length > 0;
347
+ for (const targetCheck of onFinish.run) {
348
+ if (checkLoopBudget(context, state, "on_finish", "run")) {
349
+ const errorIssue = {
350
+ file: "system",
351
+ line: 0,
352
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
353
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_finish run`,
354
+ severity: "error",
355
+ category: "logic"
356
+ };
357
+ result.issues = [...result.issues || [], errorIssue];
358
+ return;
359
+ }
360
+ const targetConfig = context.config.checks?.[targetCheck];
361
+ const fanoutMode = targetConfig?.fanout || "reduce";
362
+ if (context.debug) {
363
+ logger.info(
364
+ `[Routing] on_finish.run: scheduling ${targetCheck} with fanout=${fanoutMode}, hasForEachItems=${hasForEachItems}`
365
+ );
366
+ }
367
+ if (fanoutMode === "map" && hasForEachItems) {
368
+ for (let itemIndex = 0; itemIndex < forEachItems.length; itemIndex++) {
369
+ state.routingLoopCount++;
370
+ const itemScope = [
371
+ { check: checkId, index: itemIndex }
372
+ ];
373
+ recordRoutingEvent({
374
+ checkId,
375
+ trigger: "on_finish",
376
+ action: "run",
377
+ target: targetCheck,
378
+ source: "run",
379
+ scope: itemScope
380
+ });
381
+ emitEvent({
382
+ type: "ForwardRunRequested",
383
+ target: targetCheck,
384
+ scope: itemScope,
385
+ origin: "run"
386
+ });
387
+ queuedForward = true;
388
+ }
389
+ } else {
390
+ state.routingLoopCount++;
391
+ recordRoutingEvent({
392
+ checkId,
393
+ trigger: "on_finish",
394
+ action: "run",
395
+ target: targetCheck,
396
+ source: "run",
397
+ scope: []
398
+ });
399
+ emitEvent({
400
+ type: "ForwardRunRequested",
401
+ target: targetCheck,
402
+ scope: [],
403
+ origin: "run"
404
+ });
405
+ queuedForward = true;
406
+ }
407
+ }
408
+ }
409
+ if (onFinish.run_js) {
410
+ const dynamicTargets = await evaluateRunJs(
411
+ onFinish.run_js,
412
+ checkId,
413
+ checkConfig,
414
+ result,
415
+ context,
416
+ state
417
+ );
418
+ for (const runItem of dynamicTargets) {
419
+ const { target: targetCheck, args: runArgs } = parseRunItem(runItem);
420
+ if (checkLoopBudget(context, state, "on_finish", "run")) {
421
+ const errorIssue = {
422
+ file: "system",
423
+ line: 0,
424
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
425
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_finish run`,
426
+ severity: "error",
427
+ category: "logic"
428
+ };
429
+ result.issues = [...result.issues || [], errorIssue];
430
+ return;
431
+ }
432
+ if (context.debug) {
433
+ logger.info(
434
+ `[Routing] on_finish.run_js: scheduling ${targetCheck}${runArgs ? ", args=" + JSON.stringify(runArgs) : ""}`
435
+ );
436
+ }
437
+ state.routingLoopCount++;
438
+ recordRoutingEvent({
439
+ checkId,
440
+ trigger: "on_finish",
441
+ action: "run",
442
+ target: targetCheck,
443
+ source: "run_js",
444
+ scope
445
+ });
446
+ emitEvent({
447
+ type: "ForwardRunRequested",
448
+ target: targetCheck,
449
+ scope,
450
+ origin: "run_js",
451
+ args: runArgs
452
+ });
453
+ queuedForward = true;
454
+ }
455
+ }
456
+ const finishTransTarget = await evaluateTransitions(
457
+ onFinish.transitions,
458
+ checkId,
459
+ checkConfig,
460
+ result,
461
+ context,
462
+ state
463
+ );
464
+ if (finishTransTarget !== void 0) {
465
+ if (finishTransTarget) {
466
+ if (checkLoopBudget(context, state, "on_finish", "goto")) {
467
+ const errorIssue = {
468
+ file: "system",
469
+ line: 0,
470
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
471
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_finish goto`,
472
+ severity: "error",
473
+ category: "logic"
474
+ };
475
+ result.issues = [...result.issues || [], errorIssue];
476
+ return;
477
+ }
478
+ state.routingLoopCount++;
479
+ recordRoutingEvent({
480
+ checkId,
481
+ trigger: "on_finish",
482
+ action: "goto",
483
+ target: finishTransTarget.to,
484
+ source: "transitions",
485
+ scope,
486
+ gotoEvent: finishTransTarget.goto_event
487
+ });
488
+ emitEvent({
489
+ type: "ForwardRunRequested",
490
+ target: finishTransTarget.to,
491
+ scope,
492
+ origin: "goto_js",
493
+ gotoEvent: finishTransTarget.goto_event
494
+ });
495
+ }
496
+ return;
497
+ }
498
+ const gotoTarget = await evaluateGoto(
499
+ onFinish.goto_js,
500
+ onFinish.goto,
501
+ checkId,
502
+ checkConfig,
503
+ result,
504
+ context,
505
+ state
506
+ );
507
+ if (gotoTarget) {
508
+ if (checkLoopBudget(context, state, "on_finish", "goto")) {
509
+ const errorIssue = {
510
+ file: "system",
511
+ line: 0,
512
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
513
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_finish goto`,
514
+ severity: "error",
515
+ category: "logic"
516
+ };
517
+ result.issues = [...result.issues || [], errorIssue];
518
+ return;
519
+ }
520
+ if (context.debug) {
521
+ logger.info(`[Routing] on_finish.goto: ${gotoTarget}`);
522
+ }
523
+ state.routingLoopCount++;
524
+ recordRoutingEvent({
525
+ checkId,
526
+ trigger: "on_finish",
527
+ action: "goto",
528
+ target: gotoTarget,
529
+ source: onFinish.goto_js ? "goto_js" : "goto",
530
+ scope
531
+ });
532
+ emitEvent({
533
+ type: "ForwardRunRequested",
534
+ target: gotoTarget,
535
+ scope,
536
+ origin: "goto_js"
537
+ });
538
+ state.flags.forwardRunRequested = true;
539
+ }
540
+ if (queuedForward) {
541
+ const guardKey = `waveRetry:on_finish:${checkId}:wave:${state.wave}`;
542
+ if (!state.forwardRunGuards?.has(guardKey)) {
543
+ state.forwardRunGuards?.add(guardKey);
544
+ emitEvent({ type: "WaveRetry", reason: "on_finish" });
545
+ }
546
+ }
547
+ }
548
+ async function evaluateFailIf(checkId, result, checkConfig, context, state) {
549
+ const config = context.config;
550
+ const globalFailIf = config.fail_if;
551
+ const checkFailIf = checkConfig.fail_if;
552
+ const globalFailureConditions = config.failure_conditions;
553
+ const checkFailureConditions = checkConfig.failure_conditions;
554
+ if (!globalFailIf && !checkFailIf && !globalFailureConditions && !checkFailureConditions) {
555
+ return { failed: false, haltExecution: false };
556
+ }
557
+ const evaluator = new FailureConditionEvaluator();
558
+ const outputsRecord = {};
559
+ for (const [key] of state.stats.entries()) {
560
+ try {
561
+ const snapshotId = context.journal.beginSnapshot();
562
+ const contextView = new (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView(
563
+ context.journal,
564
+ context.sessionId,
565
+ snapshotId,
566
+ [],
567
+ context.event
568
+ );
569
+ const journalResult = contextView.get(key);
570
+ if (journalResult) {
571
+ outputsRecord[key] = journalResult;
572
+ }
573
+ } catch {
574
+ outputsRecord[key] = { issues: [] };
575
+ }
576
+ }
577
+ const checkSchema = typeof checkConfig.schema === "object" ? "custom" : checkConfig.schema || "";
578
+ const checkGroup = checkConfig.group || "";
579
+ let anyFailed = false;
580
+ let shouldHalt = false;
581
+ let haltMessage;
582
+ if (globalFailIf) {
583
+ try {
584
+ const failed = await evaluator.evaluateSimpleCondition(
585
+ checkId,
586
+ checkSchema,
587
+ checkGroup,
588
+ result,
589
+ globalFailIf,
590
+ outputsRecord
591
+ );
592
+ if (failed) {
593
+ logger.warn(`[Routing] Global fail_if triggered for ${checkId}: ${globalFailIf}`);
594
+ const failIssue = {
595
+ file: "system",
596
+ line: 0,
597
+ ruleId: "global_fail_if",
598
+ message: `Global failure condition met: ${globalFailIf}`,
599
+ severity: "error",
600
+ category: "logic"
601
+ };
602
+ result.issues = [...result.issues || [], failIssue];
603
+ }
604
+ } catch (error) {
605
+ const msg = error instanceof Error ? error.message : String(error);
606
+ logger.error(`[Routing] Error evaluating global fail_if: ${msg}`);
607
+ }
608
+ }
609
+ if (checkFailIf) {
610
+ try {
611
+ const failed = await evaluator.evaluateSimpleCondition(
612
+ checkId,
613
+ checkSchema,
614
+ checkGroup,
615
+ result,
616
+ checkFailIf,
617
+ outputsRecord
618
+ );
619
+ if (failed) {
620
+ logger.warn(`[Routing] Check fail_if triggered for ${checkId}: ${checkFailIf}`);
621
+ const failIssue = {
622
+ file: "system",
623
+ line: 0,
624
+ ruleId: `${checkId}_fail_if`,
625
+ message: `Check failure condition met: ${checkFailIf}`,
626
+ severity: "error",
627
+ category: "logic"
628
+ };
629
+ result.issues = [...result.issues || [], failIssue];
630
+ anyFailed = true;
631
+ }
632
+ } catch (error) {
633
+ const msg = error instanceof Error ? error.message : String(error);
634
+ logger.error(`[Routing] Error evaluating check fail_if: ${msg}`);
635
+ }
636
+ }
637
+ if (globalFailureConditions || checkFailureConditions) {
638
+ try {
639
+ const conditionResults = await evaluator.evaluateConditions(
640
+ checkId,
641
+ checkSchema,
642
+ checkGroup,
643
+ result,
644
+ globalFailureConditions,
645
+ checkFailureConditions,
646
+ outputsRecord
647
+ );
648
+ for (const condResult of conditionResults) {
649
+ if (condResult.failed) {
650
+ logger.warn(
651
+ `[Routing] Failure condition '${condResult.conditionName}' triggered for ${checkId}: ${condResult.expression}`
652
+ );
653
+ const failIssue = {
654
+ file: "system",
655
+ line: 0,
656
+ ruleId: `${checkId}_${condResult.conditionName}`,
657
+ message: condResult.message || `Failure condition met: ${condResult.expression}`,
658
+ severity: condResult.severity || "error",
659
+ category: "logic"
660
+ };
661
+ result.issues = [...result.issues || [], failIssue];
662
+ anyFailed = true;
663
+ if (condResult.haltExecution) {
664
+ shouldHalt = true;
665
+ haltMessage = condResult.message || `Execution halted: condition '${condResult.conditionName}' triggered`;
666
+ logger.error(
667
+ `[Routing] HALT EXECUTION triggered by '${condResult.conditionName}' for ${checkId}`
668
+ );
669
+ }
670
+ }
671
+ }
672
+ } catch (error) {
673
+ const msg = error instanceof Error ? error.message : String(error);
674
+ logger.error(`[Routing] Error evaluating failure_conditions: ${msg}`);
675
+ }
676
+ }
677
+ return { failed: anyFailed, haltExecution: shouldHalt, haltMessage };
678
+ }
679
+ function checkLoopBudget(context, state, origin, action) {
680
+ const maxLoops = context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS;
681
+ if (state.routingLoopCount >= maxLoops) {
682
+ const msg = `Routing loop budget exceeded (max_loops=${maxLoops}) during ${origin} ${action}`;
683
+ logger.error(`[Routing] ${msg}`);
684
+ return true;
685
+ }
686
+ return false;
687
+ }
688
+ async function processOnSuccess(checkId, scope, result, checkConfig, context, state, emitEvent) {
689
+ const onSuccess = checkConfig.on_success;
690
+ if (!onSuccess) {
691
+ return;
692
+ }
693
+ if (context.debug) {
694
+ logger.info(`[Routing] Processing on_success for ${checkId}`);
695
+ }
696
+ if (onSuccess.run && onSuccess.run.length > 0) {
697
+ const resForEachItems = result && result.forEachItems || void 0;
698
+ const hasForEachItems = Array.isArray(resForEachItems) && resForEachItems.length > 0;
699
+ const stepOutput = result?.output;
700
+ const depResults = {};
701
+ try {
702
+ const snapshotId = context.journal.beginSnapshot();
703
+ const allEntries = context.journal.readVisible(context.sessionId, snapshotId, context.event);
704
+ for (const entry of allEntries) {
705
+ if (entry.checkId && entry.result) {
706
+ const r = entry.result;
707
+ depResults[entry.checkId] = r.output !== void 0 ? r.output : r;
708
+ }
709
+ }
710
+ } catch (e) {
711
+ logger.warn(`[Routing] Failed to build dependency results for template rendering: ${e}`);
712
+ }
713
+ for (const runItem of onSuccess.run) {
714
+ const { target: targetCheck, args: rawArgs } = parseRunItem(runItem);
715
+ const runArgs = rawArgs ? await renderRouteArgs(rawArgs, stepOutput, depResults, context) : void 0;
716
+ if (checkLoopBudget(context, state, "on_success", "run")) {
717
+ const errorIssue = {
718
+ file: "system",
719
+ line: 0,
720
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
721
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_success run`,
722
+ severity: "error",
723
+ category: "logic"
724
+ };
725
+ result.issues = [...result.issues || [], errorIssue];
726
+ return;
727
+ }
728
+ const targetConfig = context.config.checks?.[targetCheck];
729
+ const fanoutMode = targetConfig?.fanout || "reduce";
730
+ if (context.debug) {
731
+ logger.info(
732
+ `[Routing] on_success.run: scheduling ${targetCheck} with fanout=${fanoutMode}, hasForEachItems=${hasForEachItems}${runArgs ? ", args=" + JSON.stringify(runArgs) : ""}`
733
+ );
734
+ }
735
+ if (fanoutMode === "map" && hasForEachItems) {
736
+ for (let itemIndex = 0; itemIndex < resForEachItems.length; itemIndex++) {
737
+ state.routingLoopCount++;
738
+ const itemScope = [
739
+ { check: checkId, index: itemIndex }
740
+ ];
741
+ recordRoutingEvent({
742
+ checkId,
743
+ trigger: "on_success",
744
+ action: "run",
745
+ target: targetCheck,
746
+ source: "run",
747
+ scope: itemScope
748
+ });
749
+ emitEvent({
750
+ type: "ForwardRunRequested",
751
+ target: targetCheck,
752
+ scope: itemScope,
753
+ origin: "run",
754
+ args: runArgs
755
+ });
756
+ }
757
+ } else {
758
+ state.routingLoopCount++;
759
+ recordRoutingEvent({
760
+ checkId,
761
+ trigger: "on_success",
762
+ action: "run",
763
+ target: targetCheck,
764
+ source: "run",
765
+ scope
766
+ });
767
+ emitEvent({
768
+ type: "ForwardRunRequested",
769
+ target: targetCheck,
770
+ scope,
771
+ origin: "run",
772
+ args: runArgs
773
+ });
774
+ }
775
+ }
776
+ }
777
+ if (onSuccess.run_js) {
778
+ const dynamicTargets = await evaluateRunJs(
779
+ onSuccess.run_js,
780
+ checkId,
781
+ checkConfig,
782
+ result,
783
+ context,
784
+ state
785
+ );
786
+ for (const runItem of dynamicTargets) {
787
+ const { target: targetCheck, args: runArgs } = parseRunItem(runItem);
788
+ if (checkLoopBudget(context, state, "on_success", "run")) {
789
+ const errorIssue = {
790
+ file: "system",
791
+ line: 0,
792
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
793
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? 10}) during on_success run`,
794
+ severity: "error",
795
+ category: "logic"
796
+ };
797
+ result.issues = [...result.issues || [], errorIssue];
798
+ return;
799
+ }
800
+ if (context.debug) {
801
+ logger.info(
802
+ `[Routing] on_success.run_js: scheduling ${targetCheck}${runArgs ? ", args=" + JSON.stringify(runArgs) : ""}`
803
+ );
804
+ }
805
+ state.routingLoopCount++;
806
+ recordRoutingEvent({
807
+ checkId,
808
+ trigger: "on_success",
809
+ action: "run",
810
+ target: targetCheck,
811
+ source: "run_js",
812
+ scope
813
+ });
814
+ emitEvent({
815
+ type: "ForwardRunRequested",
816
+ target: targetCheck,
817
+ scope,
818
+ origin: "run_js",
819
+ args: runArgs
820
+ });
821
+ }
822
+ }
823
+ const successTransTarget = await evaluateTransitions(
824
+ onSuccess.transitions,
825
+ checkId,
826
+ checkConfig,
827
+ result,
828
+ context,
829
+ state
830
+ );
831
+ if (successTransTarget !== void 0) {
832
+ if (successTransTarget) {
833
+ if (checkLoopBudget(context, state, "on_success", "goto")) {
834
+ const errorIssue = {
835
+ file: "system",
836
+ line: 0,
837
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
838
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_success goto`,
839
+ severity: "error",
840
+ category: "logic"
841
+ };
842
+ result.issues = [...result.issues || [], errorIssue];
843
+ return;
844
+ }
845
+ state.routingLoopCount++;
846
+ recordRoutingEvent({
847
+ checkId,
848
+ trigger: "on_success",
849
+ action: "goto",
850
+ target: successTransTarget.to,
851
+ source: "transitions",
852
+ scope,
853
+ gotoEvent: successTransTarget.goto_event
854
+ });
855
+ emitEvent({
856
+ type: "ForwardRunRequested",
857
+ target: successTransTarget.to,
858
+ scope,
859
+ origin: "goto_js",
860
+ gotoEvent: successTransTarget.goto_event
861
+ });
862
+ state.flags.forwardRunRequested = true;
863
+ }
864
+ return;
865
+ }
866
+ const gotoTarget = await evaluateGoto(
867
+ onSuccess.goto_js,
868
+ onSuccess.goto,
869
+ checkId,
870
+ checkConfig,
871
+ result,
872
+ context,
873
+ state
874
+ );
875
+ if (gotoTarget) {
876
+ if (checkLoopBudget(context, state, "on_success", "goto")) {
877
+ const errorIssue = {
878
+ file: "system",
879
+ line: 0,
880
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
881
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? 10}) during on_success goto`,
882
+ severity: "error",
883
+ category: "logic"
884
+ };
885
+ result.issues = [...result.issues || [], errorIssue];
886
+ return;
887
+ }
888
+ if (context.debug) {
889
+ logger.info(`[Routing] on_success.goto: ${gotoTarget}`);
890
+ }
891
+ state.routingLoopCount++;
892
+ recordRoutingEvent({
893
+ checkId,
894
+ trigger: "on_success",
895
+ action: "goto",
896
+ target: gotoTarget,
897
+ source: onSuccess.goto_js ? "goto_js" : "goto",
898
+ scope,
899
+ gotoEvent: onSuccess.goto_event
900
+ });
901
+ emitEvent({
902
+ type: "ForwardRunRequested",
903
+ target: gotoTarget,
904
+ gotoEvent: onSuccess.goto_event,
905
+ scope,
906
+ origin: "goto_js"
907
+ });
908
+ state.flags.forwardRunRequested = true;
909
+ }
910
+ }
911
+ async function processOnFail(checkId, scope, result, checkConfig, context, state, emitEvent) {
912
+ const defaults = context.config.routing?.defaults?.on_fail || {};
913
+ const onFail = checkConfig.on_fail ? { ...defaults, ...checkConfig.on_fail } : void 0;
914
+ if (!onFail) {
915
+ return;
916
+ }
917
+ if (context.debug) {
918
+ logger.info(`[Routing] Processing on_fail for ${checkId}`);
919
+ }
920
+ if (onFail.run && onFail.run.length > 0) {
921
+ const resForEachItems = result && result.forEachItems || void 0;
922
+ const hasForEachItems = Array.isArray(resForEachItems) && resForEachItems.length > 0;
923
+ for (const targetCheck of onFail.run) {
924
+ if (checkLoopBudget(context, state, "on_fail", "run")) {
925
+ const errorIssue = {
926
+ file: "system",
927
+ line: 0,
928
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
929
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? 10}) during on_fail run`,
930
+ severity: "error",
931
+ category: "logic"
932
+ };
933
+ result.issues = [...result.issues || [], errorIssue];
934
+ return;
935
+ }
936
+ const targetConfig = context.config.checks?.[targetCheck];
937
+ const fanoutMode = targetConfig?.fanout || "reduce";
938
+ if (context.debug) {
939
+ logger.info(
940
+ `[Routing] on_fail.run: scheduling ${targetCheck} with fanout=${fanoutMode}, hasForEachItems=${hasForEachItems}`
941
+ );
942
+ }
943
+ if (hasForEachItems) {
944
+ for (let itemIndex = 0; itemIndex < resForEachItems.length; itemIndex++) {
945
+ const itemOut = resForEachItems[itemIndex];
946
+ if (itemOut && typeof itemOut === "object" && itemOut.__failed !== true && fanoutMode !== "map") {
947
+ continue;
948
+ }
949
+ state.routingLoopCount++;
950
+ const itemScope = [
951
+ { check: checkId, index: itemIndex }
952
+ ];
953
+ recordRoutingEvent({
954
+ checkId,
955
+ trigger: "on_fail",
956
+ action: "run",
957
+ target: targetCheck,
958
+ source: "run",
959
+ scope: itemScope
960
+ });
961
+ emitEvent({
962
+ type: "ForwardRunRequested",
963
+ target: targetCheck,
964
+ scope: itemScope,
965
+ origin: "run",
966
+ sourceCheck: checkId
967
+ // The failed check that triggered on_fail.run
968
+ });
969
+ }
970
+ } else {
971
+ state.routingLoopCount++;
972
+ recordRoutingEvent({
973
+ checkId,
974
+ trigger: "on_fail",
975
+ action: "run",
976
+ target: targetCheck,
977
+ source: "run",
978
+ scope
979
+ });
980
+ emitEvent({
981
+ type: "ForwardRunRequested",
982
+ target: targetCheck,
983
+ scope,
984
+ origin: "run",
985
+ sourceCheck: checkId
986
+ // The failed check that triggered on_fail.run
987
+ });
988
+ }
989
+ }
990
+ }
991
+ if (onFail.run_js) {
992
+ const dynamicTargets = await evaluateRunJs(
993
+ onFail.run_js,
994
+ checkId,
995
+ checkConfig,
996
+ result,
997
+ context,
998
+ state
999
+ );
1000
+ for (const runItem of dynamicTargets) {
1001
+ const { target: targetCheck, args: runArgs } = parseRunItem(runItem);
1002
+ if (checkLoopBudget(context, state, "on_fail", "run")) {
1003
+ const errorIssue = {
1004
+ file: "system",
1005
+ line: 0,
1006
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
1007
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? 10}) during on_fail run`,
1008
+ severity: "error",
1009
+ category: "logic"
1010
+ };
1011
+ result.issues = [...result.issues || [], errorIssue];
1012
+ return;
1013
+ }
1014
+ if (context.debug) {
1015
+ logger.info(
1016
+ `[Routing] on_fail.run_js: scheduling ${targetCheck}${runArgs ? ", args=" + JSON.stringify(runArgs) : ""}`
1017
+ );
1018
+ }
1019
+ state.routingLoopCount++;
1020
+ recordRoutingEvent({
1021
+ checkId,
1022
+ trigger: "on_fail",
1023
+ action: "run",
1024
+ target: targetCheck,
1025
+ source: "run_js",
1026
+ scope
1027
+ });
1028
+ emitEvent({
1029
+ type: "ForwardRunRequested",
1030
+ target: targetCheck,
1031
+ scope,
1032
+ origin: "run_js",
1033
+ sourceCheck: checkId,
1034
+ // The failed check that triggered on_fail.run_js
1035
+ args: runArgs
1036
+ });
1037
+ }
1038
+ }
1039
+ if (onFail.retry && typeof onFail.retry.max === "number" && onFail.retry.max > 0) {
1040
+ const crit = getCriticality(context, checkId);
1041
+ const failureKind = classifyFailure(result);
1042
+ if ((crit === "external" || crit === "internal") && failureKind === "logical") {
1043
+ if (context.debug) {
1044
+ logger.info(
1045
+ `[Routing] on_fail.retry suppressed for ${checkId} (criticality=${crit}, failure=logical)`
1046
+ );
1047
+ }
1048
+ } else {
1049
+ const max = Math.max(0, onFail.retry.max || 0);
1050
+ if (!state.retryAttempts) state.retryAttempts = /* @__PURE__ */ new Map();
1051
+ const attemptsMap = state.retryAttempts;
1052
+ const makeKey = (sc) => {
1053
+ const keyScope = sc && sc.length > 0 ? JSON.stringify(sc) : "root";
1054
+ return `${checkId}::${keyScope}`;
1055
+ };
1056
+ const scheduleRetryForScope = (sc) => {
1057
+ const key = makeKey(sc);
1058
+ const used = attemptsMap.get(key) || 0;
1059
+ if (used >= max) return;
1060
+ attemptsMap.set(key, used + 1);
1061
+ state.routingLoopCount++;
1062
+ recordRoutingEvent({
1063
+ checkId,
1064
+ trigger: "on_fail",
1065
+ action: "retry",
1066
+ source: "retry",
1067
+ scope: sc || []
1068
+ });
1069
+ emitEvent({
1070
+ type: "ForwardRunRequested",
1071
+ target: checkId,
1072
+ scope: sc || [],
1073
+ origin: "run"
1074
+ });
1075
+ };
1076
+ const resForEachItems = result && result.forEachItems || void 0;
1077
+ const hasForEachItems = Array.isArray(resForEachItems) && resForEachItems.length > 0;
1078
+ if (hasForEachItems) {
1079
+ for (let i = 0; i < resForEachItems.length; i++) {
1080
+ const itemOut = resForEachItems[i];
1081
+ if (itemOut && typeof itemOut === "object" && itemOut.__failed === true) {
1082
+ const sc = [{ check: checkId, index: i }];
1083
+ scheduleRetryForScope(sc);
1084
+ }
1085
+ }
1086
+ } else {
1087
+ scheduleRetryForScope(scope);
1088
+ }
1089
+ }
1090
+ }
1091
+ const failTransTarget = await evaluateTransitions(
1092
+ onFail.transitions,
1093
+ checkId,
1094
+ checkConfig,
1095
+ result,
1096
+ context,
1097
+ state
1098
+ );
1099
+ if (failTransTarget !== void 0) {
1100
+ if (failTransTarget) {
1101
+ if (checkLoopBudget(context, state, "on_fail", "goto")) {
1102
+ const errorIssue = {
1103
+ file: "system",
1104
+ line: 0,
1105
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
1106
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? DEFAULT_MAX_LOOPS}) during on_fail goto`,
1107
+ severity: "error",
1108
+ category: "logic"
1109
+ };
1110
+ result.issues = [...result.issues || [], errorIssue];
1111
+ return;
1112
+ }
1113
+ state.routingLoopCount++;
1114
+ recordRoutingEvent({
1115
+ checkId,
1116
+ trigger: "on_fail",
1117
+ action: "goto",
1118
+ target: failTransTarget.to,
1119
+ source: "transitions",
1120
+ scope,
1121
+ gotoEvent: failTransTarget.goto_event
1122
+ });
1123
+ emitEvent({
1124
+ type: "ForwardRunRequested",
1125
+ target: failTransTarget.to,
1126
+ scope,
1127
+ origin: "goto_js",
1128
+ gotoEvent: failTransTarget.goto_event
1129
+ });
1130
+ state.flags.forwardRunRequested = true;
1131
+ }
1132
+ return;
1133
+ }
1134
+ const gotoTarget = await evaluateGoto(
1135
+ onFail.goto_js,
1136
+ onFail.goto,
1137
+ checkId,
1138
+ checkConfig,
1139
+ result,
1140
+ context,
1141
+ state
1142
+ );
1143
+ if (gotoTarget) {
1144
+ if (checkLoopBudget(context, state, "on_fail", "goto")) {
1145
+ const errorIssue = {
1146
+ file: "system",
1147
+ line: 0,
1148
+ ruleId: `${checkId}/routing/loop_budget_exceeded`,
1149
+ message: `Routing loop budget exceeded (max_loops=${context.config.routing?.max_loops ?? 10}) during on_fail goto`,
1150
+ severity: "error",
1151
+ category: "logic"
1152
+ };
1153
+ result.issues = [...result.issues || [], errorIssue];
1154
+ return;
1155
+ }
1156
+ if (context.debug) {
1157
+ logger.info(`[Routing] on_fail.goto: ${gotoTarget}`);
1158
+ }
1159
+ state.routingLoopCount++;
1160
+ recordRoutingEvent({
1161
+ checkId,
1162
+ trigger: "on_fail",
1163
+ action: "goto",
1164
+ target: gotoTarget,
1165
+ source: onFail.goto_js ? "goto_js" : "goto",
1166
+ scope,
1167
+ gotoEvent: onFail.goto_event
1168
+ });
1169
+ emitEvent({
1170
+ type: "ForwardRunRequested",
1171
+ target: gotoTarget,
1172
+ gotoEvent: onFail.goto_event,
1173
+ scope,
1174
+ origin: "goto_js"
1175
+ });
1176
+ state.flags.forwardRunRequested = true;
1177
+ }
1178
+ }
1179
+ function isValidRunItem(item) {
1180
+ if (typeof item === "string" && item) return true;
1181
+ if (typeof item === "object" && item !== null) {
1182
+ const obj = item;
1183
+ if (typeof obj.step === "string" && obj.step) return true;
1184
+ if (typeof obj.workflow === "string" && obj.workflow) return true;
1185
+ }
1186
+ return false;
1187
+ }
1188
+ async function evaluateRunJs(runJs, checkId, checkConfig, result, context, _state) {
1189
+ try {
1190
+ const sandbox = createSecureSandbox();
1191
+ const historyLimit = getHistoryLimit();
1192
+ const snapshotId = context.journal.beginSnapshot();
1193
+ const contextView = new (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView(
1194
+ context.journal,
1195
+ context.sessionId,
1196
+ snapshotId,
1197
+ [],
1198
+ context.event
1199
+ );
1200
+ const outputsRecord = {};
1201
+ const outputsHistory = {};
1202
+ const allEntries = context.journal.readVisible(context.sessionId, snapshotId, context.event);
1203
+ const uniqueCheckIds = new Set(allEntries.map((e) => e.checkId));
1204
+ for (const checkIdFromJournal of uniqueCheckIds) {
1205
+ try {
1206
+ const journalResult = contextView.get(checkIdFromJournal);
1207
+ if (journalResult) {
1208
+ outputsRecord[checkIdFromJournal] = journalResult.output !== void 0 ? journalResult.output : journalResult;
1209
+ }
1210
+ } catch {
1211
+ outputsRecord[checkIdFromJournal] = { issues: [] };
1212
+ }
1213
+ try {
1214
+ const history = contextView.getHistory(checkIdFromJournal);
1215
+ if (history && history.length > 0) {
1216
+ const trimmed = historyLimit && history.length > historyLimit ? history.slice(history.length - historyLimit) : history;
1217
+ outputsHistory[checkIdFromJournal] = trimmed.map(
1218
+ (r) => r.output !== void 0 ? r.output : r
1219
+ );
1220
+ }
1221
+ } catch {
1222
+ }
1223
+ }
1224
+ outputsRecord.history = outputsHistory;
1225
+ let forEachMeta = void 0;
1226
+ try {
1227
+ const hist = outputsHistory[checkId] || [];
1228
+ const lastArr = hist.slice().reverse().find((x) => Array.isArray(x));
1229
+ if (checkConfig.forEach === true && Array.isArray(lastArr)) {
1230
+ forEachMeta = {
1231
+ is_parent: true,
1232
+ last_wave_size: lastArr.length,
1233
+ last_items: lastArr
1234
+ };
1235
+ }
1236
+ } catch {
1237
+ }
1238
+ const scopeObj = {
1239
+ step: {
1240
+ id: checkId,
1241
+ tags: checkConfig.tags || [],
1242
+ group: checkConfig.group
1243
+ },
1244
+ outputs: outputsRecord,
1245
+ outputs_history: outputsHistory,
1246
+ output: result?.output,
1247
+ memory: createMemoryHelpers(),
1248
+ event: {
1249
+ name: context.event || "manual"
1250
+ },
1251
+ forEach: forEachMeta
1252
+ };
1253
+ const code = `
1254
+ const step = scope.step;
1255
+ const outputs = scope.outputs;
1256
+ const outputs_history = scope.outputs_history;
1257
+ const output = scope.output;
1258
+ const memory = scope.memory;
1259
+ const event = scope.event;
1260
+ const forEach = scope.forEach;
1261
+ const log = (...args) => console.log('\u{1F50D} Debug:', ...args);
1262
+ const __fn = () => {
1263
+ ${runJs}
1264
+ };
1265
+ const __res = __fn();
1266
+ // Return as-is; validation happens after sandbox execution
1267
+ return Array.isArray(__res) ? __res : [];
1268
+ `;
1269
+ try {
1270
+ const evalResult = compileAndRun(
1271
+ sandbox,
1272
+ code,
1273
+ { scope: scopeObj },
1274
+ { injectLog: false, wrapFunction: false }
1275
+ );
1276
+ return Array.isArray(evalResult) ? evalResult.filter(isValidRunItem) : [];
1277
+ } catch (error) {
1278
+ const msg = error instanceof Error ? error.message : String(error);
1279
+ logger.error(`[Routing] Error in run_js sandbox evaluation: ${msg}`);
1280
+ return [];
1281
+ }
1282
+ } catch (error) {
1283
+ const msg = error instanceof Error ? error.message : String(error);
1284
+ logger.error(`[Routing] Error evaluating run_js: ${msg}`);
1285
+ return [];
1286
+ }
1287
+ }
1288
+ async function evaluateGoto(gotoJs, gotoStatic, checkId, checkConfig, result, context, _state) {
1289
+ if (gotoJs) {
1290
+ try {
1291
+ const sandbox = createSecureSandbox();
1292
+ const historyLimit = getHistoryLimit();
1293
+ const snapshotId = context.journal.beginSnapshot();
1294
+ const contextView = new (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView(
1295
+ context.journal,
1296
+ context.sessionId,
1297
+ snapshotId,
1298
+ [],
1299
+ void 0
1300
+ );
1301
+ const outputsRecord = {};
1302
+ const outputsHistory = {};
1303
+ const allEntries = context.journal.readVisible(context.sessionId, snapshotId, void 0);
1304
+ const uniqueCheckIds = new Set(allEntries.map((e) => e.checkId));
1305
+ for (const checkIdFromJournal of uniqueCheckIds) {
1306
+ try {
1307
+ const journalResult = contextView.get(checkIdFromJournal);
1308
+ if (journalResult) {
1309
+ outputsRecord[checkIdFromJournal] = journalResult.output !== void 0 ? journalResult.output : journalResult;
1310
+ }
1311
+ } catch {
1312
+ outputsRecord[checkIdFromJournal] = { issues: [] };
1313
+ }
1314
+ try {
1315
+ const history = contextView.getHistory(checkIdFromJournal);
1316
+ if (history && history.length > 0) {
1317
+ const trimmed = historyLimit && history.length > historyLimit ? history.slice(history.length - historyLimit) : history;
1318
+ outputsHistory[checkIdFromJournal] = trimmed.map(
1319
+ (r) => r.output !== void 0 ? r.output : r
1320
+ );
1321
+ }
1322
+ } catch {
1323
+ }
1324
+ }
1325
+ outputsRecord.history = outputsHistory;
1326
+ let forEachMeta = void 0;
1327
+ try {
1328
+ const hist = outputsHistory[checkId] || [];
1329
+ const lastArr = hist.slice().reverse().find((x) => Array.isArray(x));
1330
+ if (checkConfig.forEach === true && Array.isArray(lastArr)) {
1331
+ forEachMeta = {
1332
+ is_parent: true,
1333
+ last_wave_size: lastArr.length,
1334
+ last_items: lastArr
1335
+ };
1336
+ }
1337
+ } catch {
1338
+ }
1339
+ const scopeObj = {
1340
+ step: {
1341
+ id: checkId,
1342
+ tags: checkConfig.tags || [],
1343
+ group: checkConfig.group
1344
+ },
1345
+ outputs: outputsRecord,
1346
+ outputs_history: outputsHistory,
1347
+ output: result?.output,
1348
+ memory: createMemoryHelpers(),
1349
+ event: {
1350
+ name: context.event || "manual"
1351
+ },
1352
+ forEach: forEachMeta
1353
+ };
1354
+ if (context.debug) {
1355
+ logger.info(
1356
+ `[Routing] evaluateGoto: checkId=${checkId}, outputs_history keys=${Object.keys(outputsHistory).join(",")}`
1357
+ );
1358
+ for (const [key, values] of Object.entries(outputsHistory)) {
1359
+ logger.info(`[Routing] ${key}: ${values.length} items`);
1360
+ }
1361
+ }
1362
+ const code = `
1363
+ const step = scope.step;
1364
+ const outputs = scope.outputs;
1365
+ const outputs_history = scope.outputs_history;
1366
+ const output = scope.output;
1367
+ const memory = scope.memory;
1368
+ const event = scope.event;
1369
+ const forEach = scope.forEach;
1370
+ const log = (...args) => console.log('\u{1F50D} Debug:', ...args);
1371
+ ${gotoJs}
1372
+ `;
1373
+ try {
1374
+ const evalResult = compileAndRun(
1375
+ sandbox,
1376
+ code,
1377
+ { scope: scopeObj },
1378
+ { injectLog: false, wrapFunction: true }
1379
+ );
1380
+ if (context.debug) {
1381
+ logger.info(`[Routing] evaluateGoto result: ${evalResult}`);
1382
+ }
1383
+ if (typeof evalResult === "string" && evalResult) {
1384
+ return evalResult;
1385
+ }
1386
+ } catch (error) {
1387
+ const msg = error instanceof Error ? error.message : String(error);
1388
+ logger.error(`[Routing] Error in goto_js sandbox evaluation: ${msg}`);
1389
+ }
1390
+ } catch (error) {
1391
+ const msg = error instanceof Error ? error.message : String(error);
1392
+ logger.error(`[Routing] Error evaluating goto_js: ${msg}`);
1393
+ if (gotoStatic) {
1394
+ logger.info(`[Routing] Falling back to static goto: ${gotoStatic}`);
1395
+ return gotoStatic;
1396
+ }
1397
+ }
1398
+ }
1399
+ return gotoStatic || null;
1400
+ }
1401
+ async function evaluateTransitions(transitions, checkId, checkConfig, result, context, _state) {
1402
+ if (!transitions || transitions.length === 0) return void 0;
1403
+ try {
1404
+ const sandbox = createSecureSandbox();
1405
+ const historyLimit = getHistoryLimit();
1406
+ const snapshotId = context.journal.beginSnapshot();
1407
+ const ContextView2 = (init_snapshot_store(), __toCommonJS(snapshot_store_exports)).ContextView;
1408
+ const view = new ContextView2(context.journal, context.sessionId, snapshotId, [], void 0);
1409
+ const outputsRecord = {};
1410
+ const outputsHistory = {};
1411
+ const allEntries = context.journal.readVisible(context.sessionId, snapshotId, void 0);
1412
+ const uniqueCheckIds = new Set(allEntries.map((e) => e.checkId));
1413
+ for (const cid of uniqueCheckIds) {
1414
+ try {
1415
+ const jr = view.get(cid);
1416
+ if (jr) outputsRecord[cid] = jr.output !== void 0 ? jr.output : jr;
1417
+ } catch {
1418
+ }
1419
+ try {
1420
+ const hist = view.getHistory(cid);
1421
+ if (hist && hist.length > 0) {
1422
+ const trimmed = historyLimit && hist.length > historyLimit ? hist.slice(hist.length - historyLimit) : hist;
1423
+ outputsHistory[cid] = trimmed.map((r) => r.output !== void 0 ? r.output : r);
1424
+ }
1425
+ } catch {
1426
+ }
1427
+ }
1428
+ outputsRecord.history = outputsHistory;
1429
+ const scopeObj = {
1430
+ step: { id: checkId, tags: checkConfig.tags || [], group: checkConfig.group },
1431
+ outputs: outputsRecord,
1432
+ outputs_history: outputsHistory,
1433
+ output: result?.output,
1434
+ memory: createMemoryHelpers(),
1435
+ event: { name: context.event || "manual" }
1436
+ };
1437
+ for (const rule of transitions) {
1438
+ const helpers = `
1439
+ const any = (arr, pred) => Array.isArray(arr) && arr.some(x => pred(x));
1440
+ const all = (arr, pred) => Array.isArray(arr) && arr.every(x => pred(x));
1441
+ const none = (arr, pred) => Array.isArray(arr) && !arr.some(x => pred(x));
1442
+ const count = (arr, pred) => Array.isArray(arr) ? arr.filter(x => pred(x)).length : 0;
1443
+ `;
1444
+ const code = `
1445
+ ${helpers}
1446
+ const step = scope.step;
1447
+ const outputs = scope.outputs;
1448
+ const outputs_history = scope.outputs_history;
1449
+ const output = scope.output;
1450
+ const memory = scope.memory;
1451
+ const event = scope.event;
1452
+ const __eval = () => { return (${rule.when}); };
1453
+ return __eval();
1454
+ `;
1455
+ let matched;
1456
+ try {
1457
+ matched = compileAndRun(
1458
+ sandbox,
1459
+ code,
1460
+ { scope: scopeObj },
1461
+ { injectLog: false, wrapFunction: false }
1462
+ );
1463
+ } catch (error) {
1464
+ const msg = error instanceof Error ? error.message : String(error);
1465
+ logger.warn(`[Routing] Error evaluating transition 'when' clause: ${msg}`);
1466
+ matched = false;
1467
+ }
1468
+ if (matched) {
1469
+ if (rule.to === null) return null;
1470
+ if (typeof rule.to === "string" && rule.to.length > 0) {
1471
+ return { to: rule.to, goto_event: rule.goto_event };
1472
+ }
1473
+ return null;
1474
+ }
1475
+ }
1476
+ return void 0;
1477
+ } catch (err) {
1478
+ logger.error(
1479
+ `[Routing] Error evaluating transitions: ${err instanceof Error ? err.message : String(err)}`
1480
+ );
1481
+ return void 0;
1482
+ }
1483
+ }
1484
+ var DEFAULT_MAX_LOOPS;
1485
+ var init_routing = __esm({
1486
+ "src/state-machine/states/routing.ts"() {
1487
+ init_logger();
1488
+ init_trace_helpers();
1489
+ init_failure_condition_evaluator();
1490
+ init_sandbox();
1491
+ init_memory_store();
1492
+ init_liquid_extensions();
1493
+ DEFAULT_MAX_LOOPS = 10;
1494
+ }
1495
+ });
1496
+
1497
+ export {
1498
+ ExecutionJournal,
1499
+ snapshot_store_exports,
1500
+ init_snapshot_store,
1501
+ handleRouting,
1502
+ checkLoopBudget,
1503
+ evaluateGoto,
1504
+ evaluateTransitions,
1505
+ init_routing
1506
+ };
1507
+ //# sourceMappingURL=chunk-RQDLVMER.mjs.map