@farmslot/recipe-runner 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +21 -0
  3. package/README.md +274 -0
  4. package/bin/farmslot-visual-review.mjs +152 -0
  5. package/dist/adapters/app-lifecycle.d.ts +41 -0
  6. package/dist/adapters/app-lifecycle.d.ts.map +1 -0
  7. package/dist/adapters/app-lifecycle.js +224 -0
  8. package/dist/adapters/app-lifecycle.js.map +1 -0
  9. package/dist/adapters/core.d.ts +5 -0
  10. package/dist/adapters/core.d.ts.map +1 -0
  11. package/dist/adapters/core.js +433 -0
  12. package/dist/adapters/core.js.map +1 -0
  13. package/dist/adapters/gesture.d.ts +12 -0
  14. package/dist/adapters/gesture.d.ts.map +1 -0
  15. package/dist/adapters/gesture.js +76 -0
  16. package/dist/adapters/gesture.js.map +1 -0
  17. package/dist/adapters/ui.d.ts +33 -0
  18. package/dist/adapters/ui.d.ts.map +1 -0
  19. package/dist/adapters/ui.js +130 -0
  20. package/dist/adapters/ui.js.map +1 -0
  21. package/dist/cli/error-output.d.ts +6 -0
  22. package/dist/cli/error-output.d.ts.map +1 -0
  23. package/dist/cli/error-output.js +19 -0
  24. package/dist/cli/error-output.js.map +1 -0
  25. package/dist/cli/index.d.ts +12 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +29 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/cli/run-command.d.ts +8 -0
  30. package/dist/cli/run-command.d.ts.map +1 -0
  31. package/dist/cli/run-command.js +253 -0
  32. package/dist/cli/run-command.js.map +1 -0
  33. package/dist/cli/support.d.ts +31 -0
  34. package/dist/cli/support.d.ts.map +1 -0
  35. package/dist/cli/support.js +297 -0
  36. package/dist/cli/support.js.map +1 -0
  37. package/dist/cli/validate-command.d.ts +4 -0
  38. package/dist/cli/validate-command.d.ts.map +1 -0
  39. package/dist/cli/validate-command.js +52 -0
  40. package/dist/cli/validate-command.js.map +1 -0
  41. package/dist/core/compose.d.ts +23 -0
  42. package/dist/core/compose.d.ts.map +1 -0
  43. package/dist/core/compose.js +104 -0
  44. package/dist/core/compose.js.map +1 -0
  45. package/dist/core/execution.d.ts +44 -0
  46. package/dist/core/execution.d.ts.map +1 -0
  47. package/dist/core/execution.js +304 -0
  48. package/dist/core/execution.js.map +1 -0
  49. package/dist/core/failure.d.ts +23 -0
  50. package/dist/core/failure.d.ts.map +1 -0
  51. package/dist/core/failure.js +43 -0
  52. package/dist/core/failure.js.map +1 -0
  53. package/dist/core/graph.d.ts +12 -0
  54. package/dist/core/graph.d.ts.map +1 -0
  55. package/dist/core/graph.js +65 -0
  56. package/dist/core/graph.js.map +1 -0
  57. package/dist/core/hud.d.ts +11 -0
  58. package/dist/core/hud.d.ts.map +1 -0
  59. package/dist/core/hud.js +120 -0
  60. package/dist/core/hud.js.map +1 -0
  61. package/dist/core/invocation.d.ts +13 -0
  62. package/dist/core/invocation.d.ts.map +1 -0
  63. package/dist/core/invocation.js +68 -0
  64. package/dist/core/invocation.js.map +1 -0
  65. package/dist/core/json.d.ts +9 -0
  66. package/dist/core/json.d.ts.map +1 -0
  67. package/dist/core/json.js +74 -0
  68. package/dist/core/json.js.map +1 -0
  69. package/dist/core/library-manifest.d.ts +53 -0
  70. package/dist/core/library-manifest.d.ts.map +1 -0
  71. package/dist/core/library-manifest.js +263 -0
  72. package/dist/core/library-manifest.js.map +1 -0
  73. package/dist/core/library.d.ts +80 -0
  74. package/dist/core/library.d.ts.map +1 -0
  75. package/dist/core/library.js +321 -0
  76. package/dist/core/library.js.map +1 -0
  77. package/dist/core/parameters.d.ts +5 -0
  78. package/dist/core/parameters.d.ts.map +1 -0
  79. package/dist/core/parameters.js +57 -0
  80. package/dist/core/parameters.js.map +1 -0
  81. package/dist/core/passive-observations.d.ts +25 -0
  82. package/dist/core/passive-observations.d.ts.map +1 -0
  83. package/dist/core/passive-observations.js +62 -0
  84. package/dist/core/passive-observations.js.map +1 -0
  85. package/dist/core/path.d.ts +7 -0
  86. package/dist/core/path.d.ts.map +1 -0
  87. package/dist/core/path.js +147 -0
  88. package/dist/core/path.js.map +1 -0
  89. package/dist/core/recording-cleanup.d.ts +10 -0
  90. package/dist/core/recording-cleanup.d.ts.map +1 -0
  91. package/dist/core/recording-cleanup.js +32 -0
  92. package/dist/core/recording-cleanup.js.map +1 -0
  93. package/dist/core/resolution-error.d.ts +7 -0
  94. package/dist/core/resolution-error.d.ts.map +1 -0
  95. package/dist/core/resolution-error.js +9 -0
  96. package/dist/core/resolution-error.js.map +1 -0
  97. package/dist/core/runner.d.ts +4 -0
  98. package/dist/core/runner.d.ts.map +1 -0
  99. package/dist/core/runner.js +738 -0
  100. package/dist/core/runner.js.map +1 -0
  101. package/dist/core/scroll-to.d.ts +111 -0
  102. package/dist/core/scroll-to.d.ts.map +1 -0
  103. package/dist/core/scroll-to.js +353 -0
  104. package/dist/core/scroll-to.js.map +1 -0
  105. package/dist/core/suite.d.ts +25 -0
  106. package/dist/core/suite.d.ts.map +1 -0
  107. package/dist/core/suite.js +76 -0
  108. package/dist/core/suite.js.map +1 -0
  109. package/dist/core/trace.d.ts +5 -0
  110. package/dist/core/trace.d.ts.map +1 -0
  111. package/dist/core/trace.js +25 -0
  112. package/dist/core/trace.js.map +1 -0
  113. package/dist/core/trust-error.d.ts +9 -0
  114. package/dist/core/trust-error.d.ts.map +1 -0
  115. package/dist/core/trust-error.js +18 -0
  116. package/dist/core/trust-error.js.map +1 -0
  117. package/dist/core/trust-input.d.ts +20 -0
  118. package/dist/core/trust-input.d.ts.map +1 -0
  119. package/dist/core/trust-input.js +68 -0
  120. package/dist/core/trust-input.js.map +1 -0
  121. package/dist/core/trust.d.ts +28 -0
  122. package/dist/core/trust.d.ts.map +1 -0
  123. package/dist/core/trust.js +284 -0
  124. package/dist/core/trust.js.map +1 -0
  125. package/dist/core/types.d.ts +319 -0
  126. package/dist/core/types.d.ts.map +1 -0
  127. package/dist/core/types.js +2 -0
  128. package/dist/core/types.js.map +1 -0
  129. package/dist/core/validation.d.ts +4 -0
  130. package/dist/core/validation.d.ts.map +1 -0
  131. package/dist/core/validation.js +18 -0
  132. package/dist/core/validation.js.map +1 -0
  133. package/dist/index.d.ts +32 -0
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +25 -0
  136. package/dist/index.js.map +1 -0
  137. package/dist/node/writers.d.ts +27 -0
  138. package/dist/node/writers.d.ts.map +1 -0
  139. package/dist/node/writers.js +99 -0
  140. package/dist/node/writers.js.map +1 -0
  141. package/dist/recording/android-mirror.d.ts +10 -0
  142. package/dist/recording/android-mirror.d.ts.map +1 -0
  143. package/dist/recording/android-mirror.js +180 -0
  144. package/dist/recording/android-mirror.js.map +1 -0
  145. package/dist/recording/capture-helper-timing.d.ts +4 -0
  146. package/dist/recording/capture-helper-timing.d.ts.map +1 -0
  147. package/dist/recording/capture-helper-timing.js +47 -0
  148. package/dist/recording/capture-helper-timing.js.map +1 -0
  149. package/dist/recording/capture-helper.d.ts +10 -0
  150. package/dist/recording/capture-helper.d.ts.map +1 -0
  151. package/dist/recording/capture-helper.js +335 -0
  152. package/dist/recording/capture-helper.js.map +1 -0
  153. package/dist/recording/cdp-video-recorder.d.ts +9 -0
  154. package/dist/recording/cdp-video-recorder.d.ts.map +1 -0
  155. package/dist/recording/cdp-video-recorder.js +319 -0
  156. package/dist/recording/cdp-video-recorder.js.map +1 -0
  157. package/dist/recording/frame-sampler.d.ts +19 -0
  158. package/dist/recording/frame-sampler.d.ts.map +1 -0
  159. package/dist/recording/frame-sampler.js +29 -0
  160. package/dist/recording/frame-sampler.js.map +1 -0
  161. package/dist/recording/timeline.d.ts +15 -0
  162. package/dist/recording/timeline.d.ts.map +1 -0
  163. package/dist/recording/timeline.js +88 -0
  164. package/dist/recording/timeline.js.map +1 -0
  165. package/dist/runtime/browser-extension.d.ts +17 -0
  166. package/dist/runtime/browser-extension.d.ts.map +1 -0
  167. package/dist/runtime/browser-extension.js +42 -0
  168. package/dist/runtime/browser-extension.js.map +1 -0
  169. package/dist/runtime/cdp.d.ts +138 -0
  170. package/dist/runtime/cdp.d.ts.map +1 -0
  171. package/dist/runtime/cdp.js +1429 -0
  172. package/dist/runtime/cdp.js.map +1 -0
  173. package/dist/runtime/decision-types.d.ts +23 -0
  174. package/dist/runtime/decision-types.d.ts.map +1 -0
  175. package/dist/runtime/decision-types.js +2 -0
  176. package/dist/runtime/decision-types.js.map +1 -0
  177. package/dist/runtime/deps-readiness.d.ts +21 -0
  178. package/dist/runtime/deps-readiness.d.ts.map +1 -0
  179. package/dist/runtime/deps-readiness.js +141 -0
  180. package/dist/runtime/deps-readiness.js.map +1 -0
  181. package/dist/runtime/log-analysis.d.ts +48 -0
  182. package/dist/runtime/log-analysis.d.ts.map +1 -0
  183. package/dist/runtime/log-analysis.js +128 -0
  184. package/dist/runtime/log-analysis.js.map +1 -0
  185. package/dist/runtime/metro-probe.d.ts +5 -0
  186. package/dist/runtime/metro-probe.d.ts.map +1 -0
  187. package/dist/runtime/metro-probe.js +24 -0
  188. package/dist/runtime/metro-probe.js.map +1 -0
  189. package/dist/runtime/operation.d.ts +32 -0
  190. package/dist/runtime/operation.d.ts.map +1 -0
  191. package/dist/runtime/operation.js +184 -0
  192. package/dist/runtime/operation.js.map +1 -0
  193. package/dist/runtime/orchestrate-up.d.ts +22 -0
  194. package/dist/runtime/orchestrate-up.d.ts.map +1 -0
  195. package/dist/runtime/orchestrate-up.js +35 -0
  196. package/dist/runtime/orchestrate-up.js.map +1 -0
  197. package/dist/runtime/react-native-bridge.d.ts +17 -0
  198. package/dist/runtime/react-native-bridge.d.ts.map +1 -0
  199. package/dist/runtime/react-native-bridge.js +57 -0
  200. package/dist/runtime/react-native-bridge.js.map +1 -0
  201. package/dist/version.d.ts +2 -0
  202. package/dist/version.d.ts.map +1 -0
  203. package/dist/version.js +8 -0
  204. package/dist/version.js.map +1 -0
  205. package/package.json +163 -0
  206. package/test/fixtures/scroll-to-visible/README.md +39 -0
  207. package/visual-review/feedback-draft.mjs +82 -0
  208. package/visual-review/index.d.mts +41 -0
  209. package/visual-review/index.mjs +4 -0
  210. package/visual-review/recipe-board.mjs +142 -0
  211. package/visual-review/review-board.mjs +981 -0
  212. package/visual-review/server.mjs +69 -0
@@ -0,0 +1,304 @@
1
+ import { normalizeRecipeRef, validateResolvedRecipeActionNode, } from '@farmslot/protocol';
2
+ import { RecipeExecutionError, recipeFailureCause, recipeFailureTraceFields } from './failure.js';
3
+ import { extractWorkflowGraph, resolveNextNode } from './graph.js';
4
+ import { isRecord } from './json.js';
5
+ import { resolveRecipeParams, resolveRecipeValue } from './parameters.js';
6
+ import { finalizeNodeObservations, resolveObserveRefs, runPassiveObservers, } from './passive-observations.js';
7
+ import { RecipeResolutionError } from './resolution-error.js';
8
+ import { recordSyntheticFailure, traceNodeMetadata } from './trace.js';
9
+ import { verifyExecutableSource } from './trust.js';
10
+ export const DEFAULT_MAX_RECIPE_CALL_DEPTH = 8;
11
+ export async function executeRecipe(options) {
12
+ const callStack = options.callStack ?? [];
13
+ const maxCallDepth = options.maxCallDepth ?? DEFAULT_MAX_RECIPE_CALL_DEPTH;
14
+ if (callStack.includes(options.ref)) {
15
+ throw new RecipeResolutionError('RECIPE_CALL_CYCLE', `Recipe call cycle detected: ${[...callStack, options.ref].join(' -> ')}.`, 'remove one call edge so the recipe dependency graph is acyclic');
16
+ }
17
+ if (callStack.length >= maxCallDepth) {
18
+ throw new RecipeResolutionError('RECIPE_CALL_DEPTH_EXCEEDED', `Recipe call depth exceeded maximum ${maxCallDepth}.`, `reduce nested recipe calls below ${maxCallDepth}`);
19
+ }
20
+ const params = resolveRecipeParams(options.ref, options.recipe, options.params);
21
+ const graph = extractWorkflowGraph(options.recipe);
22
+ const prefix = options.prefix ?? '';
23
+ const outputs = new Map();
24
+ const localOutputs = {};
25
+ const getOutput = (nodeId) => {
26
+ if (outputs.has(nodeId))
27
+ return outputs.get(nodeId);
28
+ throw new Error(`No output recorded for node ${nodeId}.`);
29
+ };
30
+ const nextCallStack = [...callStack, options.ref];
31
+ let failureCause;
32
+ const runGraph = async (entry, nodeCount, stopAfterNode) => {
33
+ let currentNodeId = entry;
34
+ let transitionCount = 0;
35
+ const maxTransitions = Math.max(1, nodeCount);
36
+ while (currentNodeId) {
37
+ const localNodeId = currentNodeId;
38
+ const namespacedNodeId = `${prefix}${localNodeId}`;
39
+ transitionCount += 1;
40
+ if (transitionCount > maxTransitions) {
41
+ recordSyntheticFailure(options.traceWriter, namespacedNodeId, new Error(`Recipe ${options.ref} exceeded its acyclic graph size.`), 'unknown', 'harness');
42
+ failureCause ??= 'harness';
43
+ return 'fail';
44
+ }
45
+ const rawNode = graph.nodes[localNodeId];
46
+ if (!rawNode) {
47
+ recordSyntheticFailure(options.traceWriter, namespacedNodeId, new Error(`Recipe ${options.ref} node ${localNodeId} does not exist.`), 'unknown', 'harness');
48
+ failureCause ??= 'harness';
49
+ return 'fail';
50
+ }
51
+ let resolvedNode;
52
+ try {
53
+ resolvedNode = resolveRecipeValue(rawNode, params, outputs);
54
+ }
55
+ catch (error) {
56
+ recordSyntheticFailure(options.traceWriter, namespacedNodeId, error instanceof Error ? error : new Error(String(error)), typeof rawNode.action === 'string' ? rawNode.action : undefined, 'harness');
57
+ failureCause ??= 'harness';
58
+ return 'fail';
59
+ }
60
+ if (!isRecord(resolvedNode)) {
61
+ recordSyntheticFailure(options.traceWriter, namespacedNodeId, new Error(`Recipe ${options.ref} node ${localNodeId} did not resolve to an object.`), 'unknown', 'harness');
62
+ failureCause ??= 'harness';
63
+ return 'fail';
64
+ }
65
+ const node = resolvedNode;
66
+ const action = String(node.action);
67
+ const startedAt = new Date();
68
+ if (action === 'end') {
69
+ const authored = terminalStatus(node.status);
70
+ // Reaching a terminal node during partial execution means the stop node never ran.
71
+ const missedStop = stopAfterNode !== undefined;
72
+ const status = missedStop ? 'fail' : authored;
73
+ const causeClass = missedStop ? 'harness' : 'subject';
74
+ const failed = status === 'fail';
75
+ options.traceWriter.record({
76
+ nodeId: namespacedNodeId,
77
+ action,
78
+ startedAt: startedAt.toISOString(),
79
+ endedAt: new Date().toISOString(),
80
+ durationMs: Date.now() - startedAt.getTime(),
81
+ ok: !failed,
82
+ ...(failed ? { cause_class: causeClass } : {}),
83
+ status,
84
+ ...(missedStop
85
+ ? {
86
+ error: `stop-after-node ${stopAfterNode} was not reached; the graph ended at ${localNodeId}.`,
87
+ }
88
+ : {}),
89
+ });
90
+ if (failed)
91
+ failureCause ??= causeClass;
92
+ return status;
93
+ }
94
+ const adapter = action === 'call' ? undefined : options.adapters.get(action);
95
+ if (action !== 'call' && !adapter) {
96
+ recordSyntheticFailure(options.traceWriter, namespacedNodeId, new Error(`No adapter registered for action ${action}.`), action, 'harness');
97
+ failureCause ??= 'harness';
98
+ return 'fail';
99
+ }
100
+ const context = options.createContext(namespacedNodeId, options.recipe, outputs, getOutput);
101
+ try {
102
+ const resolvedValidation = validateResolvedRecipeActionNode(node, options.actionManifest, {
103
+ adapter: options.adapter,
104
+ });
105
+ if (resolvedValidation.status === 'invalid') {
106
+ const resolutionError = new RecipeResolutionError('RECIPE_PARAMS_INVALID', `Resolved parameters for ${action} are invalid: ${resolvedValidation.findings
107
+ .map((finding) => `${finding.code} ${finding.path}: ${finding.message}`)
108
+ .join('; ')}`, `inspect ${action} with actions --action ${action}`);
109
+ throw new RecipeExecutionError('harness', resolutionError.message, {
110
+ cause: resolutionError,
111
+ });
112
+ }
113
+ if (options.publishHudProgress) {
114
+ const ok = await options.publishHudProgress('running', {
115
+ nodeId: namespacedNodeId,
116
+ action,
117
+ node,
118
+ recipe: options.recipe,
119
+ index: transitionCount,
120
+ total: nodeCount,
121
+ context,
122
+ });
123
+ if (!ok) {
124
+ throw new RecipeExecutionError('harness', `app.hud running update failed for ${namespacedNodeId}.`);
125
+ }
126
+ }
127
+ const result = action === 'call'
128
+ ? await executeRecipeCall({
129
+ ...options,
130
+ node,
131
+ callNodeId: namespacedNodeId,
132
+ callStack: nextCallStack,
133
+ })
134
+ : await executeAction(adapter, action, node, context);
135
+ const observeRefs = resolveObserveRefs(action, options.defaultObserverRefs);
136
+ const observationResult = action === 'call'
137
+ ? {}
138
+ : await runPassiveObservers({
139
+ action,
140
+ node,
141
+ adapter: adapter,
142
+ context,
143
+ logger: options.logger,
144
+ refs: observeRefs,
145
+ });
146
+ if (result.output !== undefined) {
147
+ localOutputs[localNodeId] = result.output;
148
+ outputs.set(localNodeId, result.output);
149
+ }
150
+ if (result.artifacts?.length)
151
+ options.registerArtifacts(result.artifacts);
152
+ const next = resolveNextNode(node, result);
153
+ if (!next) {
154
+ throw new RecipeExecutionError('harness', `Recipe node ${localNodeId} has no next target.`);
155
+ }
156
+ const { observations, observationWarnings } = finalizeNodeObservations({
157
+ result,
158
+ observationResult,
159
+ observeRefs,
160
+ });
161
+ options.traceWriter.record({
162
+ nodeId: namespacedNodeId,
163
+ action,
164
+ ...(action === 'call' ? { recipe: recipeCallTrace(node, options.recipes) } : {}),
165
+ ...traceNodeMetadata(node, result),
166
+ startedAt: startedAt.toISOString(),
167
+ endedAt: new Date().toISOString(),
168
+ durationMs: Date.now() - startedAt.getTime(),
169
+ ok: true,
170
+ next,
171
+ case: result.case,
172
+ output: result.output,
173
+ ...(result.phases?.length ? { phases: result.phases } : {}),
174
+ ...(observations ? { observations } : {}),
175
+ ...(observationWarnings.length ? { observationWarnings } : {}),
176
+ });
177
+ if (options.publishHudProgress) {
178
+ const ok = await options.publishHudProgress('pass', {
179
+ nodeId: namespacedNodeId,
180
+ action,
181
+ node,
182
+ recipe: options.recipe,
183
+ index: transitionCount,
184
+ total: nodeCount,
185
+ context,
186
+ });
187
+ if (!ok) {
188
+ // Both the completed action and the failed HUD update are already recorded.
189
+ failureCause ??= 'harness';
190
+ return 'fail';
191
+ }
192
+ }
193
+ if (localNodeId === stopAfterNode)
194
+ return 'pass';
195
+ currentNodeId = next;
196
+ }
197
+ catch (error) {
198
+ const message = error instanceof Error ? error.message : String(error);
199
+ const causeClass = recipeFailureCause(error);
200
+ failureCause ??= causeClass;
201
+ if (options.publishHudProgress) {
202
+ try {
203
+ await options.publishHudProgress('fail', {
204
+ nodeId: namespacedNodeId,
205
+ action,
206
+ node,
207
+ recipe: options.recipe,
208
+ index: transitionCount,
209
+ total: nodeCount,
210
+ context,
211
+ error: message,
212
+ });
213
+ }
214
+ catch (hudError) {
215
+ options.logger.warn(`app.hud failure update failed for ${namespacedNodeId}: ${hudError instanceof Error ? hudError.message : String(hudError)}`);
216
+ }
217
+ }
218
+ options.traceWriter.record({
219
+ nodeId: namespacedNodeId,
220
+ action,
221
+ ...(action === 'call' ? { recipe: recipeCallTrace(node, options.recipes) } : {}),
222
+ ...traceNodeMetadata(node),
223
+ startedAt: startedAt.toISOString(),
224
+ endedAt: new Date().toISOString(),
225
+ durationMs: Date.now() - startedAt.getTime(),
226
+ ok: false,
227
+ cause_class: causeClass,
228
+ error: message,
229
+ ...recipeFailureTraceFields(error),
230
+ });
231
+ return 'fail';
232
+ }
233
+ }
234
+ return 'fail';
235
+ };
236
+ const mainStatus = await runGraph(graph.entry, graph.mainNodeCount, options.stopAfterNode);
237
+ const teardownStatus = graph.teardownEntry
238
+ ? await runGraph(graph.teardownEntry, graph.teardownNodeCount)
239
+ : 'pass';
240
+ const status = combineStatuses(mainStatus, teardownStatus);
241
+ return {
242
+ status,
243
+ ...(status === 'fail' ? { failureCause: failureCause ?? 'unknown' } : {}),
244
+ output: recipeOutput(options.ref, status, localOutputs),
245
+ outputs,
246
+ };
247
+ }
248
+ async function executeRecipeCall(options) {
249
+ const ref = typeof options.node.ref === 'string' ? normalizeRecipeRef(options.node.ref) : '';
250
+ if (!ref)
251
+ throw new RecipeExecutionError('harness', 'call.ref must be a non-empty recipe id.');
252
+ const resolved = options.recipes.get(ref);
253
+ if (!resolved) {
254
+ throw new RecipeExecutionError('harness', `Recipe ${ref} is not available from the configured libraries.`);
255
+ }
256
+ const result = await executeRecipe({
257
+ ...options,
258
+ ref,
259
+ recipe: resolved.document,
260
+ params: isRecord(options.node.params) ? options.node.params : {},
261
+ prefix: `${options.callNodeId}/`,
262
+ callStack: options.callStack,
263
+ // Partial execution targets the root graph only; called recipes always run to completion.
264
+ stopAfterNode: undefined,
265
+ });
266
+ if (result.status !== 'pass') {
267
+ throw new RecipeExecutionError(result.failureCause ?? 'unknown', `Recipe ${ref} finished with status ${result.status}.`);
268
+ }
269
+ return { output: result.output };
270
+ }
271
+ function recipeCallTrace(node, recipes) {
272
+ const ref = typeof node.ref === 'string' ? normalizeRecipeRef(node.ref) : '';
273
+ const resolved = ref ? recipes.get(ref) : undefined;
274
+ const digest = resolved?.provenance.digest;
275
+ if (!resolved || !digest)
276
+ return undefined;
277
+ return {
278
+ ref,
279
+ digest,
280
+ source: resolved.source,
281
+ file: resolved.file,
282
+ ...(resolved.adapter ? { adapter: resolved.adapter } : {}),
283
+ };
284
+ }
285
+ async function executeAction(adapter, action, node, context) {
286
+ await verifyExecutableSource(adapter, `Action ${action}`);
287
+ return adapter.execute(node, context);
288
+ }
289
+ function terminalStatus(value) {
290
+ if (value === 'pass' || value === 'fail' || value === 'unknown')
291
+ return value;
292
+ throw new Error('end.status must be pass, fail, or unknown.');
293
+ }
294
+ function combineStatuses(mainStatus, teardownStatus) {
295
+ if (mainStatus === 'fail' || teardownStatus === 'fail')
296
+ return 'fail';
297
+ if (mainStatus === 'unknown' || teardownStatus === 'unknown')
298
+ return 'unknown';
299
+ return 'pass';
300
+ }
301
+ function recipeOutput(ref, status, outputs) {
302
+ return { ref, status, outputs };
303
+ }
304
+ //# sourceMappingURL=execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/core/execution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { RecipeFailureCause } from '@farmslot/protocol';
2
+ declare const RECIPE_EXECUTION_ERROR_BRAND: unique symbol;
3
+ export interface RecipeExecutionErrorOptions extends ErrorOptions {
4
+ /** Stable machine-readable failure code recorded as trace error_code. */
5
+ code?: string;
6
+ /** Observation at the moment of failure, recorded as trace error_details. */
7
+ details?: unknown;
8
+ }
9
+ export declare class RecipeExecutionError extends Error {
10
+ readonly [RECIPE_EXECUTION_ERROR_BRAND] = true;
11
+ readonly causeClass: RecipeFailureCause;
12
+ readonly code?: string;
13
+ readonly details?: unknown;
14
+ constructor(causeClass: RecipeFailureCause, message: string, options?: RecipeExecutionErrorOptions);
15
+ }
16
+ /** Trace fields for a coded execution failure; empty for uncoded errors. */
17
+ export declare function recipeFailureTraceFields(error: unknown): {
18
+ error_code?: string;
19
+ error_details?: unknown;
20
+ };
21
+ export declare function recipeFailureCause(error: unknown, fallback?: RecipeFailureCause): RecipeFailureCause;
22
+ export {};
23
+ //# sourceMappingURL=failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure.d.ts","sourceRoot":"","sources":["../../src/core/failure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,QAAA,MAAM,4BAA4B,eAA6D,CAAC;AAQhG,MAAM,WAAW,2BAA4B,SAAQ,YAAY;IAC/D,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,CAAC,4BAA4B,CAAC,QAAQ;IAC/C,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;gBAGzB,UAAU,EAAE,kBAAkB,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,2BAA2B;CAQxC;AAWD,4EAA4E;AAC5E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAMA;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,kBAA8B,GACvC,kBAAkB,CAKpB"}
@@ -0,0 +1,43 @@
1
+ var _a;
2
+ const RECIPE_EXECUTION_ERROR_BRAND = Symbol.for('@farmslot/recipe-runner/RecipeExecutionError');
3
+ const FAILURE_CAUSES = new Set([
4
+ 'subject',
5
+ 'harness',
6
+ 'environment',
7
+ 'unknown',
8
+ ]);
9
+ export class RecipeExecutionError extends Error {
10
+ static { _a = RECIPE_EXECUTION_ERROR_BRAND; }
11
+ constructor(causeClass, message, options) {
12
+ super(message, options);
13
+ this[_a] = true;
14
+ this.name = 'RecipeExecutionError';
15
+ this.causeClass = causeClass;
16
+ if (options?.code !== undefined)
17
+ this.code = options.code;
18
+ if (options?.details !== undefined)
19
+ this.details = options.details;
20
+ }
21
+ }
22
+ function isRecipeExecutionError(error) {
23
+ return Boolean(error &&
24
+ typeof error === 'object' &&
25
+ RECIPE_EXECUTION_ERROR_BRAND in error &&
26
+ error[RECIPE_EXECUTION_ERROR_BRAND] === true);
27
+ }
28
+ /** Trace fields for a coded execution failure; empty for uncoded errors. */
29
+ export function recipeFailureTraceFields(error) {
30
+ if (!isRecipeExecutionError(error))
31
+ return {};
32
+ return {
33
+ ...(typeof error.code === 'string' ? { error_code: error.code } : {}),
34
+ ...(error.details !== undefined ? { error_details: error.details } : {}),
35
+ };
36
+ }
37
+ export function recipeFailureCause(error, fallback = 'unknown') {
38
+ if (isRecipeExecutionError(error) && FAILURE_CAUSES.has(error.causeClass)) {
39
+ return error.causeClass;
40
+ }
41
+ return fallback;
42
+ }
43
+ //# sourceMappingURL=failure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure.js","sourceRoot":"","sources":["../../src/core/failure.ts"],"names":[],"mappings":";AAEA,MAAM,4BAA4B,GAAG,MAAM,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;AAChG,MAAM,cAAc,GAAG,IAAI,GAAG,CAAqB;IACjD,SAAS;IACT,SAAS;IACT,aAAa;IACb,SAAS;CACV,CAAC,CAAC;AASH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;kBACnC,4BAA4B;IAKtC,YACE,UAA8B,EAC9B,OAAe,EACf,OAAqC;QAErC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAVjB,QAA8B,GAAG,IAAI,CAAC;QAW7C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,OAAO,EAAE,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1D,IAAI,OAAO,EAAE,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACrE,CAAC;CACF;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,OAAO,OAAO,CACZ,KAAK;QACL,OAAO,KAAK,KAAK,QAAQ;QACzB,4BAA4B,IAAI,KAAK;QACrC,KAAK,CAAC,4BAA4B,CAAC,KAAK,IAAI,CAC7C,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,wBAAwB,CAAC,KAAc;IAIrD,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9C,OAAO;QACL,GAAG,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,KAAc,EACd,WAA+B,SAAS;IAExC,IAAI,sBAAsB,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,UAAU,CAAC;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ActionResult } from './types.js';
2
+ export interface WorkflowGraph {
3
+ entry: string;
4
+ nodes: Record<string, Record<string, unknown>>;
5
+ teardownEntry?: string;
6
+ mainNodeIds: ReadonlySet<string>;
7
+ mainNodeCount: number;
8
+ teardownNodeCount: number;
9
+ }
10
+ export declare function extractWorkflowGraph(recipe: unknown): WorkflowGraph;
11
+ export declare function resolveNextNode(node: Record<string, unknown>, result: Pick<ActionResult, 'case'>): string | undefined;
12
+ //# sourceMappingURL=graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/core/graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,CAwBnE;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GACjC,MAAM,GAAG,SAAS,CAkBpB"}
@@ -0,0 +1,65 @@
1
+ import { isRecord } from './json.js';
2
+ export function extractWorkflowGraph(recipe) {
3
+ if (!isRecord(recipe) || !isRecord(recipe.workflow)) {
4
+ throw new Error('Recipe must include workflow.');
5
+ }
6
+ const workflow = recipe.workflow;
7
+ if (typeof workflow.entry !== 'string' || !workflow.entry || !isRecord(workflow.nodes)) {
8
+ throw new Error('Recipe workflow must include entry and nodes.');
9
+ }
10
+ const nodes = Object.fromEntries(Object.entries(workflow.nodes).filter((entry) => isRecord(entry[1])));
11
+ const teardownEntry = typeof workflow.teardown === 'string' ? workflow.teardown : undefined;
12
+ const mainNodes = reachableNodes(nodes, workflow.entry);
13
+ const teardownNodes = teardownEntry ? reachableNodes(nodes, teardownEntry) : new Set();
14
+ return {
15
+ entry: workflow.entry,
16
+ nodes,
17
+ ...(teardownEntry ? { teardownEntry } : {}),
18
+ mainNodeIds: mainNodes,
19
+ mainNodeCount: mainNodes.size,
20
+ teardownNodeCount: teardownNodes.size,
21
+ };
22
+ }
23
+ export function resolveNextNode(node, result) {
24
+ if (result.case != null) {
25
+ if (!isRecord(node.cases)) {
26
+ throw new Error(`Action returned case ${result.case}, but the recipe node declares no cases.`);
27
+ }
28
+ const target = node.cases[result.case];
29
+ if (typeof target !== 'string') {
30
+ throw new Error(`Action returned unmapped case ${result.case}.`);
31
+ }
32
+ return target;
33
+ }
34
+ if (isRecord(node.cases)) {
35
+ if (typeof node.default !== 'string')
36
+ throw new Error('Branch node has no default target.');
37
+ return node.default;
38
+ }
39
+ return typeof node.next === 'string' ? node.next : undefined;
40
+ }
41
+ function reachableNodes(nodes, entry) {
42
+ const reachable = new Set();
43
+ const queue = [entry];
44
+ while (queue.length) {
45
+ const nodeId = queue.shift();
46
+ if (!nodeId || reachable.has(nodeId))
47
+ continue;
48
+ const node = nodes[nodeId];
49
+ if (!node)
50
+ continue;
51
+ reachable.add(nodeId);
52
+ if (typeof node.next === 'string')
53
+ queue.push(node.next);
54
+ if (typeof node.default === 'string')
55
+ queue.push(node.default);
56
+ if (isRecord(node.cases)) {
57
+ for (const target of Object.values(node.cases)) {
58
+ if (typeof target === 'string')
59
+ queue.push(target);
60
+ }
61
+ }
62
+ }
63
+ return reachable;
64
+ }
65
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/core/graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { RecipeHudOptions } from './types.js';
2
+ export declare function buildHudNode(status: 'running' | 'pass' | 'fail', event: {
3
+ nodeId: string;
4
+ action: string;
5
+ node: Record<string, unknown>;
6
+ recipe: unknown;
7
+ index: number;
8
+ total: number;
9
+ error?: string;
10
+ }, options: RecipeHudOptions | false | undefined): Record<string, unknown>;
11
+ //# sourceMappingURL=hud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hud.d.ts","sourceRoot":"","sources":["../../src/core/hud.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,EACnC,KAAK,EAAE;IACL,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,OAAO,EAAE,gBAAgB,GAAG,KAAK,GAAG,SAAS,GAC5C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6BzB"}
@@ -0,0 +1,120 @@
1
+ import { isRecord } from './json.js';
2
+ export function buildHudNode(status, event, options) {
3
+ const title = options && options.title
4
+ ? options.title
5
+ : isRecord(event.recipe) && typeof event.recipe.title === 'string'
6
+ ? event.recipe.title
7
+ : 'Recipe run';
8
+ const flow = hudFlow(event.action, event.node);
9
+ const text = hudText(event.action, status, event.node);
10
+ const detail = normalizeHudSecondary(hudDetail(event.node), text, flow);
11
+ return {
12
+ action: 'app.hud',
13
+ title,
14
+ status,
15
+ node_id: event.nodeId,
16
+ phase: lifecyclePhase(status),
17
+ flow: flow || undefined,
18
+ detail,
19
+ text,
20
+ action_name: event.action,
21
+ proves: event.node.proves,
22
+ intent: text,
23
+ error: event.error ? hudErrorSummary(event.error) : undefined,
24
+ display: isRecord(event.node.display) ? event.node.display : hudDisplay(options),
25
+ progress: {
26
+ current: event.index,
27
+ total: event.total,
28
+ },
29
+ };
30
+ }
31
+ function hudDisplay(options) {
32
+ if (!options || !options.display)
33
+ return {};
34
+ return { ...options.display };
35
+ }
36
+ function lifecyclePhase(status) {
37
+ if (status === 'running')
38
+ return 'running';
39
+ if (status === 'fail')
40
+ return 'failed';
41
+ return 'passed';
42
+ }
43
+ function hudFlow(_action, node) {
44
+ for (const key of ['flow', 'domain', 'group']) {
45
+ const value = node[key];
46
+ if (typeof value === 'string' && value.trim())
47
+ return value;
48
+ }
49
+ return '';
50
+ }
51
+ function hudText(action, status, node) {
52
+ const intent = node.intent;
53
+ if (typeof intent === 'string' && intent.trim())
54
+ return intent;
55
+ if (action === 'end') {
56
+ if (status === 'fail')
57
+ return 'Recipe failed';
58
+ if (status === 'pass')
59
+ return 'Recipe completed';
60
+ return 'Recipe is finishing';
61
+ }
62
+ throw new Error('Non-terminal recipe nodes must include intent before HUD progress can render.');
63
+ }
64
+ function hudDetail(node) {
65
+ const explicitDetail = node.detail;
66
+ if (typeof explicitDetail === 'string' && explicitDetail.trim())
67
+ return explicitDetail;
68
+ const fragments = [];
69
+ for (const key of ['target', 'destination', 'selector', 'test_id', 'testID']) {
70
+ const value = node[key];
71
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
72
+ fragments.push(`${key}=${String(value)}`);
73
+ }
74
+ }
75
+ return fragments.length ? fragments.join(' · ') : undefined;
76
+ }
77
+ function normalizeHudSecondary(value, intent, flow) {
78
+ const normalized = value?.trim();
79
+ if (!normalized)
80
+ return undefined;
81
+ if (normalized === intent || normalized === flow)
82
+ return undefined;
83
+ return normalized;
84
+ }
85
+ function hudErrorSummary(error) {
86
+ const nestedError = error.match(/"error":"([^"]+)"/)?.[1];
87
+ const lines = error
88
+ .split('\n')
89
+ .map((line) => line.trim())
90
+ .filter((line) => {
91
+ if (!line)
92
+ return false;
93
+ if (line.includes("Warning: The 'NO_COLOR' env"))
94
+ return false;
95
+ if (line.startsWith('(Use `node --trace-warnings'))
96
+ return false;
97
+ if (line.startsWith('file://'))
98
+ return false;
99
+ if (line.startsWith('at '))
100
+ return false;
101
+ if (line.startsWith('Node.js '))
102
+ return false;
103
+ return true;
104
+ });
105
+ const errorLine = [...lines].reverse().find((line) => line.startsWith('Error: ')) ??
106
+ lines.find((line) => line.includes('Error: ')) ??
107
+ lines[0] ??
108
+ error;
109
+ let summary = errorLine.includes('Error: ')
110
+ ? errorLine.slice(errorLine.indexOf('Error: ') + 'Error: '.length)
111
+ : errorLine;
112
+ const resultIndex = summary.indexOf('. Result:');
113
+ if (resultIndex > 0)
114
+ summary = summary.slice(0, resultIndex);
115
+ if (nestedError && !summary.includes(nestedError))
116
+ summary = `${summary}: ${nestedError}`;
117
+ const maxLength = 180;
118
+ return summary.length > maxLength ? `${summary.slice(0, maxLength - 1)}…` : summary;
119
+ }
120
+ //# sourceMappingURL=hud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hud.js","sourceRoot":"","sources":["../../src/core/hud.ts"],"names":[],"mappings":"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"}