@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
package/CHANGELOG.md ADDED
@@ -0,0 +1,255 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@farmslot/recipe-runner` (published as `@farmslot/recipe-harness` up to 0.22.1) are tracked here.
4
+
5
+ ## Unreleased
6
+
7
+ - Active-development baseline; add user-facing changes here before release or package publication.
8
+
9
+ ## 0.23.0 - 2026-10-04
10
+
11
+ - **Breaking:** renamed from `@farmslot/recipe-harness`. Run provenance, the bundled recipe source and the packages a library's `requires` can name now report `@farmslot/recipe-runner`. `RECIPE_HARNESS_VERSION`, `runRecipeHarnessCli`, `createRecipeHarnessProgram` and `RecipeHarnessCliOptions` are now `RECIPE_RUNNER_VERSION`, `runRecipeRunnerCli`, `createRecipeRunnerProgram` and `RecipeRunnerCliOptions`. There is no `@farmslot/recipe-harness` alias package.
12
+ - Publish with protocol 0.34.0.
13
+
14
+ ## 0.22.1 - 2026-10-03
15
+
16
+ - `@farmslot/recipe-harness/cli` no longer uses top-level await, so CommonJS consumers can `require()` it and every other package entry, `@farmslot/recipe-cli` included. Running `dist/cli/index.js` directly still starts the CLI and exits 1 with the error message on failure.
17
+
18
+ ## 0.22.0 - 2026-10-02
19
+
20
+ - Keep run plan digests stable across repeated `yarn <script>` runs: only the values Yarn changes per invocation or derives from the package (its shim paths, `npm_package_*`, user agent, `INIT_CWD`/`PROJECT_CWD`, Corepack root) leave the approved environment; user-set `npm_config_*` and `COREPACK_*` settings stay bound. Log the `Recipe libraries:` line as soon as libraries load, so early failures keep it. `run` and `validate` exit 2 for a malformed `--library` or `RECIPE_LIBRARY_PATH` entry, and a library root that does not exist fails with `RECIPE_LIBRARY_PATH_INVALID` instead of a raw ENOENT.
21
+ - Recognize custom recipe adapter folders from the active adapter or a library's platform manifest. Preserve built-in adapters and qualified custom references across library precedence.
22
+ - **Breaking:** the `farmslot-recipe` bin moves to `@farmslot/recipe-cli`; install that package (or `npx -p @farmslot/recipe-cli farmslot-recipe`) instead of running it from `@farmslot/recipe-harness`. `recipe-library.json` keys are all optional and gain `adapters`, `actions` and `requires`; `requires` is enforced on every load and fails closed for packages the host cannot check. Library files load and digest through one walker that skips dot-entries, `node_modules` and symlinked directories and rejects files outside the library root. A `--library` entry replaces the `RECIPE_LIBRARY_PATH` entry with the same name, `run` accepts `<library>.<ref>` ids, and `run` records each library's content digest (line-ending independent) in its provenance. `run` records the selected recipe (`recipeSelection`) in `summary.json` and only warns about shadows it executes. A malformed library path entry fails with `RECIPE_LIBRARY_PATH_INVALID`. Export the library helpers discovery tools need.
23
+
24
+ ## 0.21.1 - 2026-09-29
25
+
26
+ - Keep operation records, logs and newly created runtime directories readable under restrictive inherited umasks.
27
+
28
+ ## 0.21.0 - 2026-09-29
29
+
30
+ - Retain invocation-scoped command stages, timings and logs for live operation observers.
31
+
32
+ ## 0.20.0 - 2026-09-28
33
+
34
+ - Prefer capture-helper's native frame and snapshot timing, wait for its first recorded frame, and retain trace-linked action markers; preserve variable frame timing for browser recording fallback.
35
+ - Use active recording-session screenshots and an owned Android mirror for physical-device capture, with explicit fallback provenance and process cleanup.
36
+
37
+ ## 0.19.0 - 2026-09-27
38
+
39
+ - The visual review board can reopen a downloaded or Companion-exported feedback JSON (`Open feedback JSON`), keeping surface and capture ids and refusing malformed feedback or feedback for another capture, and every page, the index included, shows whether the file opened. Drafts are stored per capture; `feedbackDraftFromDocument` exposes the same restore for tests and other renderers.
40
+ - Add canonical `ui.scroll_to`: one harness algorithm over a provider `withScrollSession` hook (implemented for CDP) that no-ops when the target is already in the HUD-safe viewport, moves once, waits for geometry to settle and verifies the final bounds; contract failures are `harness` with stable `SCROLL_*` codes and geometry in trace `error_code`/`error_details`. `ui.scroll` now separates absolute `offset_x`/`offset_y` from relative `delta_x`/`delta_y` (a lone `delta_x` no longer adds a 600px vertical step). Add `stopAfterNode` / `--stop-after-node` to run the graph through one node and then its declared teardown.
41
+
42
+ ## 0.18.1 - 2026-09-21
43
+
44
+ - Retain typed, redacted invocation parameters with the recipe digest and execution summary; canonical artifact validation now reads those inputs for parameterized runs and rejects mismatches or redacted credentials.
45
+
46
+ ## 0.18.0 - 2026-09-20
47
+
48
+ - Published against `@farmslot/protocol` 0.30.0 so one protocol copy serves every dependent (child checklist units and the acceptance ledger arrive through that pin).
49
+
50
+ ## 0.17.0 - 2026-09-18
51
+
52
+ - Publish against `@farmslot/protocol` 0.29.0 so downstream installs resolve one protocol version.
53
+
54
+ ## 0.16.3 - 2026-09-17
55
+
56
+ - Publish against `@farmslot/protocol` 0.28.0 so a consumer that also installs `@farmslot/agent-runtime` 0.10.0 resolves one protocol copy.
57
+
58
+ ## 0.16.2 - 2026-09-13
59
+
60
+ - Publish against `@farmslot/protocol` 0.26.0 so a consumer that also installs `@farmslot/agent-runtime` 0.9.0 resolves one protocol copy.
61
+ - Clear selected text before typing a replacement during CDP recipe playback.
62
+
63
+ ## 0.16.1 - 2026-09-09
64
+
65
+ - Include native form controls and checkbox/radio/switch roles in browser readiness hit tests, so an actionable modal does not block its own setup.
66
+
67
+ ## 0.16.0 - 2026-09-07
68
+
69
+ - Wait for stable CDP click targets, refresh contexts invalidated by navigation before dispatch, and run app restart preparation only once.
70
+ - Reserve `recipes/shared/` for cross-adapter recipes while preserving their domain names, duplicate checks, and adapter-specific override precedence.
71
+ - Preserve completed action output and a single trace entry when HUD completion fails; retain the failed run verdict and execute teardown.
72
+
73
+ ## 0.15.1 - 2026-08-28
74
+
75
+ - Classify unresolved relative or absolute bundle imports as source errors instead of missing package dependencies, while retaining missing-package precedence for mixed failures.
76
+
77
+ ## 0.15.0 - 2026-08-14
78
+
79
+ - Align the packaged Recipe Protocol dependency with 0.21.0 so consumers use one execution-capability and evidence contract runtime.
80
+
81
+ ## 0.14.0 - 2026-08-03
82
+
83
+ - feat(visual-review): start navigation maps at the top level with independently collapsible branches and expand/collapse-all controls.
84
+ - feat(visual-review): label multi-platform captures as variants of one surface and expose an explicit Compare mode.
85
+ - feat(visual-review): provide a lightweight project-agnostic review-board builder, recipe-artifact converter, and dynamic-port server with self-contained route/capture feedback plus color-coded, movable point and drag-area annotations.
86
+ - feat(visual-review): default multi-platform boards to the platform from the latest build, remember the operator's iOS/Android selection across pages, and keep an explicit All comparison mode.
87
+ - feat(recipe): standardize `ui.capture_surface` and implement full-page CDP evidence capture.
88
+
89
+ ## 0.13.0 - 2026-08-02
90
+
91
+ - **BREAKING:** Add canonical `recipes/<adapter>/<domain>/*.recipe.json`
92
+ discovery and reserve top-level adapter directory names. Stable ids and
93
+ temporary legacy suffixes remain supported; resolution errors are actionable
94
+ and deterministic across `run` and `validate`.
95
+
96
+ ## 0.12.1 - 2026-08-02
97
+
98
+ - Resolve CDP navigation URLs outside the page realm so LavaMoat-scuttled Extension pages can use shared navigation actions.
99
+
100
+ ## 0.12.0 - 2026-08-02
101
+
102
+ - **BREAKING:** Replace `ui.gesture` with streamed swipe, pan, drag, and long-press transports; use `hold_ms`; reject unsupported active-adapter parameters after template resolution; and retain coordinate phases through explicit transport-result envelopes.
103
+
104
+ ## 0.11.1 - 2026-08-01
105
+
106
+ - fix: keep iOS Simulator lifecycle restarts idempotent when `simctl` reports that it found nothing to terminate.
107
+
108
+ ## 0.11.0 - 2026-08-01
109
+
110
+ - **BREAKING:** Run summaries now include structured totals and all four failure-cause counts required by the matching `@farmslot/protocol`; publish the protocol first and update harness consumers as one coordinated release.
111
+ - feat: preserve structured failure ownership in run evidence and finalize frozen suite scopes from completed recipe results or explicit non-execution records.
112
+
113
+ ## 0.10.6 - 2026-07-31
114
+
115
+ - fix: scroll hardened browser pages through the document root without accessing scuttled window globals.
116
+
117
+ ## 0.10.5 - 2026-07-31
118
+
119
+ - fix: retry DOM-settlement and compositor probes when navigation invalidates their frame or execution context, report transient or superseded probe races as suspended results or warnings instead of throws or false success, and preserve the public isolated-world evaluator across navigation.
120
+
121
+ ## 0.10.4 - 2026-07-31
122
+
123
+ - fix: evaluate CDP DOM-settlement probes in a navigation-resilient isolated world so LavaMoat scuttling cannot break post-interaction readiness checks.
124
+
125
+ ## 0.10.3 - 2026-07-30
126
+
127
+ - fix: publish the protocol workspace dependency as its concrete npm version for external consumers.
128
+
129
+ ## 0.10.2 - 2026-07-30
130
+
131
+ - fix: avoid scuttled browser globals when matching visible text and producing observation selectors in hardened Extension pages.
132
+ - fix: expose npm-semver dependency version checks for host runtime-readiness bootstraps.
133
+
134
+ ## 0.10.1 - 2026-07-30
135
+
136
+ - fix: capture-helper doctor failures report `capture_helper_exec_failed` (spawn/PATH/env) instead of claiming the tool is missing when only execution failed.
137
+ - fix: retry the compositor probe in a CDP isolated world when a hardened page blocks injected `requestAnimationFrame` access.
138
+
139
+ ## 0.10.0 - 2026-07-24
140
+
141
+ - **BREAKING:** Read action support from the keyed manifest allowlist and derive recipe-library identity from configuration or path, removing redundant per-library metadata.
142
+ - Record the canonical action-manifest schema in run summaries.
143
+ - Bind passive observers to trust plans and emit the package version in CLI and run metadata.
144
+
145
+ ## 0.9.4 - 2026-07-24
146
+
147
+ - Bound CDP HTTP discovery and abort stalled responses within the caller deadline.
148
+
149
+ ## 0.9.3 - 2026-07-24
150
+
151
+ - Bound CDP WebSocket connection setup with an optional timeout that terminates stalled client handshakes.
152
+
153
+ ## 0.9.2 - 2026-07-24
154
+
155
+ - Detect reachable-but-suspended browser pages with a read-only compositor probe.
156
+ - Treat the active Yarn linker marker as dependency-install authority and ignore uncertified legacy baselines.
157
+
158
+ ## 0.9.1 - 2026-07-23
159
+
160
+ - Preserve the current Mobile route when foregrounding an app instead of reopening its launch URL.
161
+ - Accept finite numeric values in `ui.set_input` by converting them to decimal text.
162
+
163
+ ## 0.9.0 - 2026-07-22
164
+
165
+ - **BREAKING:** Unify direct and nested execution on parameterized recipes, one ordered recipe index, and one recursive executor; remove the separate reusable graph CLI/runtime.
166
+ - Emit `recipe-resolution.json` plus exact digest-keyed reachable recipes and expose recipe list/describe discovery.
167
+ - Preflight nested parameters, depth, trust, and dependency paths before side effects; resolution failures include stable recovery guidance.
168
+ - Validate composed artifact packages from their retained dependency graph without requiring the source library.
169
+ - Discover an adjacent `recipe-library/` for task-authored recipes.
170
+
171
+ ## 0.8.0 - 2026-07-19
172
+
173
+ - Added provenance-aware preflight/execution planning that blocks restricted capabilities from unknown or untrusted sources before side effects; approvals bind to the exact resolved plan digest
174
+ - Included automatic HUD execution in the approved plan
175
+ - Bound approvals to the project root, artifact destination, and effective run environment
176
+ - Fixed source-swap and symlink boundary bypasses across custom implementations, project reads, flow catalogs, and artifact/video writes
177
+ - Fixed managed-run approval recovery instructions and caller-selected library trust defaults
178
+ - Added an explicit-environment mode so host wrappers can exclude internal control variables from recipe execution and approval identity
179
+
180
+ ## 0.7.0 - 2026-07-19
181
+
182
+ - Added `flows describe <ref>` with resolved provenance, parameter schema/defaults, the complete flow definition, and an authored call node or clearly labeled template in human and stable JSON output.
183
+
184
+ ## 0.6.0 - 2026-07-13
185
+
186
+ - fix: require Yarn's `node_modules/.yarn-state.yml` install surface when `nodeLinker: node-modules`, so a leftover `.yarn/install-state.gz` cannot report removed dependencies as current
187
+
188
+ ## 0.5.0 - 2026-07-12
189
+
190
+ - feat: record passive UI observations for default and node-level observe policies in recipe traces, including replayable controls inside open shadow roots without exposing input values as labels.
191
+ - fix: dependency readiness trusts install markers newer than dependency inputs even when an older recorded baseline exists, preventing unnecessary reinstall prompts in managed slots.
192
+ - fix: use workspace-linked `@farmslot/protocol` during local development so package builds cannot resolve a stale published sibling package.
193
+
194
+ ## 0.4.3 - 2026-07-09
195
+
196
+ - fix: dependency readiness no longer treats an old recorded baseline as stale when install markers are newer than `package.json`/`yarn.lock`, avoiding repeated unnecessary reinstall prompts in managed slots
197
+
198
+ ## 0.4.2 - 2026-07-09
199
+
200
+ - feat: a run that composes flows now emits `resolved-recipe.json` — the authored recipe with every reachable flow (inline, `uses`, or library, transitively) inlined under `flows`. This artifact is self-contained and validates as a complete recipe without the library
201
+ - feat: export `composeRecipe` / `buildResolvedRecipe` — the shared composition step used by the runner (executed path) and the CLI static resolve-check to derive the same `resolved-recipe.json`
202
+
203
+ ## 0.4.1 - 2026-07-08
204
+
205
+ - `watch_logs` now defaults to run-scoped matching using file offsets captured at recipe start across the main workflow and called flows, so markers written before the run cannot satisfy log assertions. Use `scope: "file"` to explicitly scan the whole file
206
+
207
+ ## 0.4.0 - 2026-07-07
208
+
209
+ - Add a standard outer `app.lifecycle` adapter for Android and iOS simulator launch/foreground/terminate/restart lifecycle control, with Android background support for performance recipes. Exported as `@farmslot/recipe-harness/adapters/app-lifecycle`.
210
+
211
+ ## 0.3.3 - 2026-07-03
212
+
213
+ - `resolved-flows.json` is emitted whenever a run had any library resolution activity (used, overridden, or shadowed flows) — previously a run that overrode every library flow with recipe-local declarations produced no artifact even though `summary.json` recorded the overrides
214
+ - `flows promote` fails loudly, naming every offending catalog file, when the target library already declares the ref in more than one catalog (pre-existing corruption); `--force` no longer overwrites just one of the duplicates and leaves the library unloadable
215
+ - Multi-source recipe library resolution: `call` refs can resolve from ordered, named library sources (`--library name=path`, `RECIPE_LIBRARY_PATH`, or the personal library at `<farmslot home>/recipe-library`). First source wins; recipe-local flows always win. Nothing resolves silently for any consumer: cross-source shadowing and recipe-local overrides are recorded in `summary.json` `flowResolution` (`shadowed`, `overrides`) and in the `resolved-flows.json` artifact alongside the used definitions, in addition to logging
216
+ - `farmslot-recipe flows list` — list library flows with source, description, required params, and last-verified date across configured sources; exits non-zero when no source is configured
217
+ - `farmslot-recipe validate --library` — validate accepts library-resolved `call` refs with the same source resolution as run
218
+ - `farmslot-recipe flows promote` — promote an inline flow from a per-change recipe into a recipe library (default: the personal library, created on first promote). Enforces the catalog contract (description required, postcondition required for `ensure_*`), stamps `provenance.promotedFrom`/`promotedAt`, and stamps `lastVerified` only from a passing run's artifacts (`--run <dir>`)
219
+
220
+ ## 0.3.2 - 2026-06-30
221
+
222
+ - Document `orchestrateRuntimeUp` `build` decision as terminal — hosts must call again after native build finishes.
223
+ - Use the installed `capture-helper` package for capture runs.
224
+
225
+ ## 0.3.1 - 2026-06-26
226
+
227
+ - Add `runtime/orchestrate-up` — generic install → relaunch decision loop (`orchestrateRuntimeUp`) for product runners to wrap with shell/platform actions.
228
+
229
+ ## 0.3.0 - 2026-06-26
230
+
231
+ - Add shared runtime-readiness helpers under `@farmslot/recipe-harness/runtime/*`:
232
+ - `deps-readiness` — install fingerprint, baseline recording, product-marker partial checks, decision state persistence
233
+ - `log-analysis` — Metro/RN bundle log boundaries, unresolved-module scoping, persistent bundle-error detection
234
+ - `metro-probe` — packager `/status` reachability probe
235
+ - `decision-types` — portable `RuntimeDecisionReport` / `RuntimeDecisionAction` shapes
236
+ - Product runners (e.g. MetaMask) should import these modules instead of copying readiness logic locally.
237
+
238
+ ## 0.2.2 - 2026-06-10
239
+
240
+ - Publish with npm-resolvable `@farmslot/protocol` dependency metadata instead of workspace-only protocol references.
241
+
242
+ ## 0.2.1 - 2026-06-10
243
+
244
+ - Drive CDP text inputs with trusted keyboard insertion instead of direct DOM value assignment so React-controlled inputs receive real input/change handling.
245
+ - Drive CDP clicks with real mouse events and expose `ui.key_press` through the standard UI adapter.
246
+
247
+ ## 0.2.0 - 2026-06-02
248
+
249
+ - Define the v0 public harness package surface with explicit core, adapter, node, CLI, and runtime entry points.
250
+ - Publish recipe runner runtime helpers under explicit `runtime/*` subpaths for browser extension, CDP, and React Native bridge clients.
251
+ - Keep CLI and writer implementation details behind explicit subpath exports instead of wildcard package exports.
252
+
253
+ ## 0.1.0 - 2026-05-31
254
+
255
+ - Initial public active-development release.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arthur Breton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # @farmslot/recipe-runner
2
+
3
+ Generic Recipe Protocol v1 runner. It executes parameterized recipe graphs through registered actions and writes portable evidence.
4
+
5
+ Canonical references:
6
+
7
+ - [Recipe runner architecture](https://farmslot.io/docs/architecture/recipe-runner)
8
+ - [Recipe Protocol v1](https://farmslot.io/docs/reference/recipe-protocol-v1)
9
+ - [Recipe Runner Protocol](https://farmslot.io/docs/reference/recipe-runner-protocol)
10
+ - [Recipe composition quality](https://farmslot.io/docs/reference/recipe-composition-quality)
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ yarn add @farmslot/recipe-runner @farmslot/protocol
16
+ # or
17
+ npm install @farmslot/recipe-runner @farmslot/protocol
18
+ ```
19
+
20
+ ## Model
21
+
22
+ - An **action** is one atomic runner capability.
23
+ - A **recipe** is one executable graph that can run directly or through a `call` node.
24
+ - Root and called recipes use the same validator, parameter rules, graph executor, observers, and trace.
25
+ - The complete static call graph and trust plan resolve before side effects.
26
+
27
+ The harness owns graph execution, standard actions, library resolution, trust preflight, and evidence writers. Projects own platform transports and namespaced domain actions.
28
+
29
+ ## Source layout
30
+
31
+ - `src/core/` — validation, composition, execution, trust, and libraries.
32
+ - `src/adapters/` — standard core and UI adapters.
33
+ - `src/runtime/` — shared CDP, browser-extension, React Native, and readiness helpers.
34
+ - `src/cli/` and `src/node/` — CLI behavior and evidence writers.
35
+ - `test/` — public behavior and package-boundary tests.
36
+
37
+ ## Minimal runner
38
+
39
+ ```ts
40
+ import { createRecipeRunner, createStandardCoreAdapters } from '@farmslot/recipe-runner';
41
+ import { getRecipeActionManifestActionNames } from '@farmslot/protocol';
42
+
43
+ const runner = createRecipeRunner({
44
+ actionManifest,
45
+ adapters: createStandardCoreAdapters({
46
+ actions: getRecipeActionManifestActionNames(actionManifest),
47
+ }),
48
+ });
49
+
50
+ const result = await runner.run({
51
+ recipePath: 'recipes/smoke.recipe.json',
52
+ params: { environment: 'local' },
53
+ artifactsDir: 'artifacts/recipe-run',
54
+ projectRoot: process.cwd(),
55
+ });
56
+
57
+ if (result.status !== 'pass') process.exitCode = 1;
58
+ ```
59
+
60
+ Runner construction and preflight fail when a required action, adapter, precondition, dependency recipe, digest, or approval is missing.
61
+
62
+ ## CLI
63
+
64
+ The `farmslot-recipe` command ships in [`@farmslot/recipe-cli`](https://farmslot.io/docs/reference/recipe-discovery), which also adds library-wide discovery (`actions`, `list`, `describe`, `explain`, `search`, `template`). This package keeps the programmatic `run`/`validate` program at `@farmslot/recipe-runner/cli`.
65
+
66
+ Discover first:
67
+
68
+ ```bash
69
+ farmslot-recipe run --list --adapter core
70
+ farmslot-recipe run service.smoke --describe --adapter core
71
+ ```
72
+
73
+ Run a library recipe with typed `key=value` parameters:
74
+
75
+ ```bash
76
+ farmslot-recipe run service.smoke environment=local retries=2 \
77
+ --adapter core \
78
+ --library team=../team-recipes \
79
+ --action-manifest action-manifest.json \
80
+ --artifacts-dir artifacts/recipe-run
81
+ ```
82
+
83
+ A recipe path works in place of a library id. UI, CDP, React Native, browser-extension, and domain actions require a project runner that registers those adapters.
84
+
85
+ ## Recipe libraries
86
+
87
+ ```text
88
+ recipes/
89
+ shared/wallet/ensure_unlocked.recipe.json
90
+ extension/checkout/smoke.recipe.json
91
+ mobile/checkout/smoke.recipe.json
92
+ ```
93
+
94
+ Recipe ids derive from their path below `recipes/`. Configure a source as
95
+ `name=/path` when its provenance label should differ from the directory name.
96
+ The first directory is the scope: `core`, `extension`, `mobile`, or `shared`.
97
+ Domains sit underneath. Scope does not become part of the id: the shared recipe
98
+ is `wallet.ensure_unlocked`, and both platform examples are `checkout.smoke`.
99
+ Keep one shared graph when only inputs differ; use an adapter variant when the
100
+ behavior differs. An exact adapter variant takes precedence over its shared
101
+ counterpart within the same source. Legacy `smoke.mobile.recipe.json` and
102
+ `smoke.extension.recipe.json` paths remain readable during migration. A recipe
103
+ must not declare its adapter through both forms, and canonical and legacy files
104
+ for the same adapter/id are rejected as duplicates. Unscoped generic paths
105
+ remain readable, but new libraries use scope-first folders. The four scope
106
+ directory names are reserved; a shared recipe cannot also declare an adapter
107
+ in its filename.
108
+
109
+ Sources are ordered and the first source wins. Configure repeatable `--library name=path`, `RECIPE_LIBRARY_PATH`, or the personal library under the Farmslot home. Shadows are reported. Duplicate ids within one source and escaping symlinks are rejected.
110
+
111
+ A `call` node resolves from the same index as direct `run`:
112
+
113
+ ```json
114
+ {
115
+ "action": "call",
116
+ "ref": "wallet.ensure_unlocked",
117
+ "params": { "account": "dev1" },
118
+ "intent": "Prepare the proof account",
119
+ "next": "verify"
120
+ }
121
+ ```
122
+
123
+ ## Evidence
124
+
125
+ Each run writes:
126
+
127
+ - `recipe.json` — exact authored root;
128
+ - `recipe-resolution.json` — root/dependency digests, selected sources, adapter variants, and call edges;
129
+ - `resolved-recipes/<sha256>.recipe.json` — exact reachable dependency documents;
130
+ - `summary.json`;
131
+ - `trace.json`;
132
+ - `artifact-manifest.json`.
133
+
134
+ Only reachable recipes are retained. Artifact validation verifies every recipe, digest, and edge.
135
+
136
+ Failed trace entries also record an explicit ownership class. Assertion
137
+ mismatches are `subject`; harness-owned machinery and unavailable prerequisites
138
+ must emit their structured classes; untyped failures remain `unknown`. Summary
139
+ cause counts reconcile exactly with the failed trace entries.
140
+
141
+ A non-zero `command` exit is untyped and remains `unknown`; callers that can
142
+ prove ownership must raise `RecipeExecutionError` with the appropriate class.
143
+
144
+ ## Suite evidence
145
+
146
+ Freeze scope before executing cases, then finalize already-completed runs. The
147
+ finalizer copies retained summaries into one portable suite package; it never
148
+ schedules cases or invents non-execution reasons.
149
+
150
+ ```ts
151
+ import { finalizeRecipeSuite, freezeRecipeSuiteScope } from '@farmslot/recipe-runner';
152
+
153
+ const frozen = freezeRecipeSuiteScope(scopeJson);
154
+ const suite = await finalizeRecipeSuite({
155
+ scope: frozen,
156
+ outputDir: 'artifacts/suite',
157
+ resolutions: [
158
+ { id: 'smoke', kind: 'verdict', result: completedRun },
159
+ {
160
+ id: 'hardware',
161
+ kind: 'not_executed',
162
+ reason_class: 'needs_manual',
163
+ detail: 'Requires hardware confirmation.',
164
+ },
165
+ ],
166
+ });
167
+ ```
168
+
169
+ ## Custom action
170
+
171
+ ```ts
172
+ import { defineActionAdapter } from '@farmslot/recipe-runner';
173
+
174
+ export const echoAdapter = defineActionAdapter({
175
+ action: 'example.echo',
176
+ async execute(node, context) {
177
+ const message = String(node.message ?? '');
178
+ context.logger.info(`echo: ${message}`);
179
+ return { output: { message } };
180
+ },
181
+ });
182
+ ```
183
+
184
+ Declare `example.echo` in the action manifest. Keep action names durable and namespaced; task-specific claims belong in recipes.
185
+
186
+ ## UI transport
187
+
188
+ ```ts
189
+ import { createStandardUiAdapters } from '@farmslot/recipe-runner';
190
+
191
+ const uiAdapters = createStandardUiAdapters({
192
+ actions: ['ui.press', 'ui.set_input', 'ui.scroll', 'ui.screenshot', 'app.hud'],
193
+ transport: {
194
+ execute(action, node, context) {
195
+ return projectUiBridge.execute(action, node, context);
196
+ },
197
+ },
198
+ });
199
+ ```
200
+
201
+ Use `ui.*` for user-visible proof and domain actions for deterministic setup/teardown. Never mutate app state to manufacture evidence. HUD text should state the current human intent; detailed diagnostics belong in trace.
202
+
203
+ ## Visual review boards
204
+
205
+ Turn visual capture nodes from any Recipe v1 run into a static annotation board:
206
+
207
+ ```bash
208
+ farmslot-visual-review build-recipe recipe.json \
209
+ --artifacts artifacts \
210
+ --platform ios \
211
+ --source-id metamask-mobile-farm:perps-surfaces \
212
+ --project metamask-mobile-farm
213
+ ```
214
+
215
+ The recipe supplies capture paths plus optional `visual_review` hierarchy, related links, and typed
216
+ navigation edges (`tab`, `push`, `in-place`, `modal`, or `replace`). The shared tool copies the
217
+ images, emits `visual-review-source.json`, and builds the navigation/annotation board; projects do
218
+ not need a renderer.
219
+
220
+ Feedback downloads as `visual-feedback.json` (`VisualReviewFeedbackDocument`). **Open feedback
221
+ JSON** reopens a document for the same source id, from this board or another renderer, keeping
222
+ surface and capture ids; `feedbackDraftFromDocument` is the same restore for code.
223
+
224
+ ## Public imports
225
+
226
+ - `@farmslot/recipe-runner`
227
+ - `/runner`, `/types`, `/writers`
228
+ - `/adapters/core`, `/adapters/ui`
229
+ - `/runtime/cdp`, `/runtime/react-native-bridge`, `/runtime/browser-extension`
230
+ - `/runtime/deps-readiness`, `/runtime/log-analysis`, `/runtime/metro-probe`
231
+ - `/runtime/decision-types`, `/runtime/orchestrate-up`
232
+ - `/cli`, `/cli/support`
233
+ - `/visual-review`
234
+
235
+ Other `src/` modules are internal.
236
+
237
+ ## Security
238
+
239
+ - Unknown or untrusted recipes preflight before side effects.
240
+ - Approval binds the resolved recipe graph, action implementations, environment, project root, and artifact destination.
241
+ - Approved custom code still has the current user's OS permissions; plan approval is not a sandbox.
242
+ - Custom adapters declare source provenance and a pinned or resolved digest.
243
+ - Keep secrets out of recipes, HUD text, trace, screenshots, and artifact paths.
244
+
245
+ ## Maintenance rules
246
+
247
+ Keep generic execution here and product/domain behavior in project adapters. Update the protocol, exports, tests, docs, and `CHANGELOG.md` together when the public contract changes.
248
+
249
+ ## Local quality
250
+
251
+ ```bash
252
+ yarn workspace @farmslot/recipe-runner quality
253
+ yarn test:recipe-runner
254
+ ```
255
+
256
+ Do not publish unless protocol, docs, exports, and tests agree.
257
+
258
+ ## License
259
+
260
+ MIT. See [LICENSE](LICENSE).
261
+
262
+ ### Retained execution parameters
263
+
264
+ Runs include `recipe-invocation.json`, indexed in the artifact manifest and bound
265
+ to the recipe digest and summary. `validate --artifact-dir` uses these recorded
266
+ parameters automatically; it never substitutes a later caller's inputs. Existing
267
+ non-parameterized packages remain valid. Older parameterized runs without saved
268
+ inputs still require their original parameters through the validation API.
269
+
270
+ Credential-bearing fields are redacted. Public `api_key_index`/`apiKeyIndex`
271
+ values are retained only when declared as integers and supplied as nonnegative
272
+ safe integers. Packages with redacted inputs fail parameter validation explicitly;
273
+ use fixture references rather than credentials in recipe parameters. The evidence
274
+ digest detects accidental mismatch, not malicious forgery of an entire package.