waygraph 0.15.54 → 0.16.1

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 (552) hide show
  1. package/README.md +8 -3
  2. package/bin/waygraph +2 -2
  3. package/dist/analysis/check.d.ts +38 -0
  4. package/dist/analysis/check.js +87 -0
  5. package/dist/analysis/coverage-gap.d.ts +1 -1
  6. package/dist/analysis/coverage-gap.js +14 -37
  7. package/dist/analysis/flow-source.d.ts +9 -0
  8. package/dist/analysis/flow-source.js +25 -0
  9. package/dist/analysis/graph.d.ts +10 -14
  10. package/dist/analysis/graph.js +48 -371
  11. package/dist/analysis/map-check.js +4 -39
  12. package/dist/analysis/practices-check.d.ts +1 -1
  13. package/dist/analysis/practices-check.js +24 -45
  14. package/dist/cli/args.d.ts +23 -0
  15. package/dist/cli/args.js +20 -0
  16. package/dist/{cli.d.ts → cli/cli.d.ts} +0 -1
  17. package/dist/{cli.js → cli/cli.js} +10 -9
  18. package/dist/{commands → cli/commands}/agent-dive-scaffold.js +35 -64
  19. package/dist/cli/commands/agent-dive.js +42 -0
  20. package/dist/cli/commands/browser.d.ts +2 -0
  21. package/dist/cli/commands/browser.js +109 -0
  22. package/dist/{commands → cli/commands}/check.d.ts +0 -1
  23. package/dist/cli/commands/check.js +104 -0
  24. package/dist/cli/commands/codemod-checkpoints.d.ts +18 -0
  25. package/dist/cli/commands/codemod-checkpoints.js +186 -0
  26. package/dist/cli/commands/codemod-flows.d.ts +18 -0
  27. package/dist/cli/commands/codemod-flows.js +284 -0
  28. package/dist/cli/commands/codemod-stubs.d.ts +10 -0
  29. package/dist/cli/commands/codemod-stubs.js +187 -0
  30. package/dist/{commands → cli/commands}/extensions.js +5 -4
  31. package/dist/{commands → cli/commands}/init.js +1 -2
  32. package/dist/{commands → cli/commands}/list.js +9 -7
  33. package/dist/cli/commands/manifest.d.ts +2 -0
  34. package/dist/cli/commands/manifest.js +20 -0
  35. package/dist/cli/commands/map.js +57 -0
  36. package/dist/cli/commands/pilot.d.ts +2 -0
  37. package/dist/cli/commands/pilot.js +102 -0
  38. package/dist/{commands → cli/commands}/run.d.ts +0 -1
  39. package/dist/cli/commands/run.js +64 -0
  40. package/dist/cli/commands/session-ops.d.ts +3 -0
  41. package/dist/cli/commands/session-ops.js +257 -0
  42. package/dist/cli/commands/session.js +132 -0
  43. package/dist/{commands → cli/commands}/test.js +11 -14
  44. package/dist/cli/commands/traverse.js +105 -0
  45. package/dist/{commands → cli/commands}/try.js +29 -25
  46. package/dist/{commands → cli/commands}/upgrade.js +40 -4
  47. package/dist/cli/flags.d.ts +193 -16
  48. package/dist/cli/flags.js +179 -234
  49. package/dist/cli/run-chain.d.ts +1 -0
  50. package/dist/cli/run-chain.js +42 -7
  51. package/dist/cli/usage.d.ts +1 -1
  52. package/dist/cli/usage.js +21 -53
  53. package/dist/cli/util.d.ts +2 -2
  54. package/dist/cli/util.js +2 -3
  55. package/dist/{highlights → demo/narration}/css.d.ts +1 -1
  56. package/dist/{highlights → demo/narration}/css.js +2 -3
  57. package/dist/{highlights → demo/narration}/demo-pace.d.ts +4 -12
  58. package/dist/{highlights → demo/narration}/demo-pace.js +5 -11
  59. package/dist/{highlights → demo/narration}/device.d.ts +4 -4
  60. package/dist/{highlights → demo/narration}/device.js +1 -1
  61. package/dist/demo/narration/merge.d.ts +10 -0
  62. package/dist/demo/narration/merge.js +67 -0
  63. package/dist/demo/narration/narration.d.ts +39 -0
  64. package/dist/{highlights/run-phase.js → demo/narration/narration.js} +25 -94
  65. package/dist/{highlights → demo/narration}/shorthand.d.ts +1 -1
  66. package/dist/demo/narration/stub-ctx.d.ts +8 -0
  67. package/dist/demo/narration/stub-ctx.js +164 -0
  68. package/dist/{highlights → demo/narration}/style.d.ts +1 -7
  69. package/dist/{highlights → demo/narration}/style.js +1 -41
  70. package/dist/{highlights → demo/narration}/todo-dock.d.ts +8 -8
  71. package/dist/{highlights → demo/narration}/todo-dock.js +13 -30
  72. package/dist/demo/overlay/auto-chrome.d.ts +7 -0
  73. package/dist/demo/overlay/auto-chrome.js +97 -0
  74. package/dist/demo/overlay/cursor.d.ts +19 -0
  75. package/dist/demo/overlay/cursor.js +142 -0
  76. package/dist/demo/overlay/device-stage.d.ts +26 -0
  77. package/dist/demo/overlay/device-stage.js +396 -0
  78. package/dist/demo/overlay/inpage/banner.d.ts +2 -0
  79. package/dist/demo/overlay/inpage/banner.js +160 -0
  80. package/dist/demo/overlay/inpage/caption.d.ts +2 -0
  81. package/dist/demo/overlay/inpage/caption.js +24 -0
  82. package/dist/demo/overlay/inpage/core.d.ts +2 -0
  83. package/dist/demo/overlay/inpage/core.js +345 -0
  84. package/dist/demo/overlay/inpage/device-chip.d.ts +1 -0
  85. package/dist/demo/overlay/inpage/device-chip.js +191 -0
  86. package/dist/demo/overlay/inpage/network.d.ts +10 -0
  87. package/dist/demo/overlay/inpage/network.js +189 -0
  88. package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -0
  89. package/dist/demo/overlay/inpage/panel-chrome.js +203 -0
  90. package/dist/demo/overlay/inpage/stamp.d.ts +1 -0
  91. package/dist/demo/overlay/inpage/stamp.js +46 -0
  92. package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -0
  93. package/dist/demo/overlay/inpage/swipe-zoom.js +220 -0
  94. package/dist/demo/overlay/inpage/todos.d.ts +2 -0
  95. package/dist/demo/overlay/inpage/todos.js +293 -0
  96. package/dist/demo/overlay/locator-theater.d.ts +25 -0
  97. package/dist/demo/overlay/locator-theater.js +76 -0
  98. package/dist/demo/overlay/network-capture.d.ts +22 -0
  99. package/dist/demo/overlay/network-capture.js +127 -0
  100. package/dist/demo/overlay/overlay-css.d.ts +3 -0
  101. package/dist/demo/overlay/overlay-css.js +369 -0
  102. package/dist/demo/overlay/overlay-stage.d.ts +31 -0
  103. package/dist/demo/overlay/overlay-stage.js +106 -0
  104. package/dist/demo/overlay/overlay.d.ts +10 -0
  105. package/dist/demo/overlay/overlay.js +89 -0
  106. package/dist/{pilot-overlay/overlay-fixtures.d.ts → demo/overlay/phase-fixtures.d.ts} +2 -2
  107. package/dist/{pilot-overlay/overlay-fixtures.js → demo/overlay/phase-fixtures.js} +2 -2
  108. package/dist/{pilot-overlay/action-ring.js → demo/overlay/pilot/actions.js} +2 -1
  109. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.d.ts +6 -5
  110. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.js +19 -18
  111. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.d.ts +2 -2
  112. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.js +13 -22
  113. package/dist/demo/overlay/reattach.d.ts +7 -0
  114. package/dist/demo/overlay/reattach.js +23 -0
  115. package/dist/demo/overlay/rings.d.ts +61 -0
  116. package/dist/demo/overlay/rings.js +422 -0
  117. package/dist/{ui → demo/overlay/ui}/components/ring.js +2 -2
  118. package/dist/{ui → demo/overlay/ui}/overlay.css +4 -4
  119. package/dist/{ui → demo/overlay/ui}/shadow.d.ts +1 -1
  120. package/dist/{ui → demo/overlay/ui}/shadow.js +39 -2
  121. package/dist/demo/stepper/after.d.ts +3 -0
  122. package/dist/demo/stepper/after.js +103 -0
  123. package/dist/demo/stepper/banner-log.d.ts +35 -0
  124. package/dist/demo/stepper/banner-log.js +65 -0
  125. package/dist/demo/stepper/before.d.ts +4 -0
  126. package/dist/demo/stepper/before.js +110 -0
  127. package/dist/demo/stepper/demo-log.d.ts +48 -0
  128. package/dist/demo/stepper/demo-log.js +292 -0
  129. package/dist/demo/stepper/gate.d.ts +11 -0
  130. package/dist/demo/stepper/gate.js +78 -0
  131. package/dist/demo/stepper/interaction-patch.d.ts +4 -0
  132. package/dist/demo/stepper/interaction-patch.js +323 -0
  133. package/dist/demo/stepper/pacing.d.ts +21 -0
  134. package/dist/demo/stepper/pacing.js +23 -0
  135. package/dist/demo/stepper/panel-after.d.ts +17 -0
  136. package/dist/demo/stepper/panel-after.js +166 -0
  137. package/dist/demo/stepper/panel-before.d.ts +12 -0
  138. package/dist/demo/stepper/panel-before.js +241 -0
  139. package/dist/demo/stepper/slides.d.ts +23 -0
  140. package/dist/demo/stepper/slides.js +233 -0
  141. package/dist/demo/stepper/step-panels.d.ts +69 -0
  142. package/dist/demo/stepper/step-panels.js +172 -0
  143. package/dist/demo/stepper/stepper.d.ts +24 -0
  144. package/dist/demo/stepper/stepper.js +122 -0
  145. package/dist/demo/stepper/teardown.d.ts +47 -0
  146. package/dist/demo/stepper/teardown.js +178 -0
  147. package/dist/demo/stepper/todo-advance.d.ts +15 -0
  148. package/dist/demo/stepper/todo-advance.js +110 -0
  149. package/dist/demo/stepper/view.d.ts +58 -0
  150. package/dist/demo/stepper/view.js +31 -0
  151. package/dist/demo/types.d.ts +85 -0
  152. package/dist/demo/verbose-log.js +15 -0
  153. package/dist/engine/block/action-page.d.ts +53 -0
  154. package/dist/engine/block/action-page.js +1 -0
  155. package/dist/{types.d.ts → engine/block/block.d.ts} +102 -142
  156. package/dist/{core → engine/block}/block.js +12 -130
  157. package/dist/engine/block/branch.d.ts +17 -0
  158. package/dist/engine/block/branch.js +40 -0
  159. package/dist/{core → engine/block}/compose.d.ts +9 -7
  160. package/dist/{core → engine/block}/compose.js +1 -1
  161. package/dist/engine/block/dialog.d.ts +13 -0
  162. package/dist/engine/block/dialog.js +37 -0
  163. package/dist/{core/blocks → engine/block/kinds}/api.d.ts +16 -12
  164. package/dist/{core/blocks → engine/block/kinds}/api.js +26 -18
  165. package/dist/{core/blocks → engine/block/kinds}/effect.d.ts +13 -18
  166. package/dist/engine/block/kinds/effect.js +17 -0
  167. package/dist/{core/blocks → engine/block/kinds}/method.d.ts +17 -29
  168. package/dist/{core/blocks → engine/block/kinds}/method.js +6 -21
  169. package/dist/{core/blocks → engine/block/kinds}/nav.d.ts +21 -31
  170. package/dist/{core/blocks → engine/block/kinds}/nav.js +6 -12
  171. package/dist/{core/blocks → engine/block/kinds}/page.d.ts +14 -20
  172. package/dist/{core/blocks → engine/block/kinds}/page.js +5 -7
  173. package/dist/engine/checkpoint/checkpoint.d.ts +22 -0
  174. package/dist/engine/checkpoint/checkpoint.js +8 -0
  175. package/dist/engine/checkpoint/route.d.ts +28 -0
  176. package/dist/engine/checkpoint/route.js +28 -0
  177. package/dist/{core → engine}/config.d.ts +7 -2
  178. package/dist/engine/config.js +6 -0
  179. package/dist/engine/engine.d.ts +45 -0
  180. package/dist/{core → engine}/engine.js +6 -10
  181. package/dist/engine/env.d.ts +59 -0
  182. package/dist/engine/env.js +83 -0
  183. package/dist/{errors.d.ts → engine/errors.d.ts} +22 -22
  184. package/dist/{errors.js → engine/errors.js} +22 -22
  185. package/dist/{core → engine/flow}/branch-regression.d.ts +7 -7
  186. package/dist/{core → engine/flow}/branch-regression.js +4 -3
  187. package/dist/engine/flow/flow.d.ts +162 -0
  188. package/dist/engine/flow/flow.js +244 -0
  189. package/dist/engine/flow/map-branch.d.ts +9 -0
  190. package/dist/engine/flow/map-branch.js +57 -0
  191. package/dist/{core → engine/flow}/map-builder.d.ts +34 -54
  192. package/dist/engine/flow/map-builder.js +242 -0
  193. package/dist/engine/flow/map-steps.d.ts +30 -0
  194. package/dist/engine/flow/map-steps.js +87 -0
  195. package/dist/{core → engine}/locate.d.ts +1 -1
  196. package/dist/{core → engine}/locate.js +1 -2
  197. package/dist/{mem-stub.d.ts → engine/mem/mem-stub.d.ts} +9 -8
  198. package/dist/{mem-stub.js → engine/mem/mem-stub.js} +2 -2
  199. package/dist/{mem-page.d.ts → engine/mem/mem.d.ts} +1 -1
  200. package/dist/{mem-page.js → engine/mem/mem.js} +2 -1
  201. package/dist/engine/page-gone.d.ts +5 -0
  202. package/dist/engine/page-gone.js +20 -0
  203. package/dist/engine/run/connect.d.ts +28 -0
  204. package/dist/{types.js → engine/run/connect.js} +11 -10
  205. package/dist/engine/run/events.d.ts +67 -0
  206. package/dist/engine/run/events.js +90 -0
  207. package/dist/engine/run/hooks.d.ts +16 -0
  208. package/dist/engine/run/hooks.js +8 -0
  209. package/dist/engine/run/launch.d.ts +13 -0
  210. package/dist/engine/run/launch.js +27 -0
  211. package/dist/{core/run-graph.d.ts → engine/run/run.d.ts} +8 -12
  212. package/dist/{core/run-graph.js → engine/run/run.js} +22 -12
  213. package/dist/engine/stub/pace.d.ts +12 -0
  214. package/dist/engine/stub/pace.js +2 -0
  215. package/dist/engine/stub/ring.d.ts +130 -0
  216. package/dist/engine/stub/ring.js +41 -0
  217. package/dist/engine/stub/stub.d.ts +268 -0
  218. package/dist/engine/stub/stub.js +1 -0
  219. package/dist/engine/stub/todos.d.ts +104 -0
  220. package/dist/engine/stub/todos.js +2 -0
  221. package/dist/engine/stub/viewport.d.ts +26 -0
  222. package/dist/engine/stub/viewport.js +2 -0
  223. package/dist/{trait.d.ts → engine/trait/trait.d.ts} +1 -1
  224. package/dist/{trait.js → engine/trait/trait.js} +1 -1
  225. package/dist/index.d.ts +88 -36
  226. package/dist/index.js +46 -19
  227. package/dist/live/auto/auto.d.ts +22 -0
  228. package/dist/live/auto/auto.js +207 -0
  229. package/dist/{session/auto-explore.d.ts → live/auto/explore.d.ts} +4 -14
  230. package/dist/{session/auto-explore.js → live/auto/explore.js} +21 -127
  231. package/dist/live/auto/mem.d.ts +11 -0
  232. package/dist/live/auto/mem.js +85 -0
  233. package/dist/live/auto/menu.d.ts +30 -0
  234. package/dist/live/auto/menu.js +335 -0
  235. package/dist/live/auto-session/auto-session.d.ts +113 -0
  236. package/dist/live/auto-session/auto-session.js +452 -0
  237. package/dist/live/auto-session/console.d.ts +4 -0
  238. package/dist/live/auto-session/console.js +41 -0
  239. package/dist/live/auto-session/files.d.ts +44 -0
  240. package/dist/live/auto-session/files.js +145 -0
  241. package/dist/{auto-session → live/auto-session}/helpers.d.ts +9 -5
  242. package/dist/{auto-session → live/auto-session}/helpers.js +18 -1
  243. package/dist/live/auto-session/inspect.d.ts +4 -0
  244. package/dist/live/auto-session/inspect.js +75 -0
  245. package/dist/{session/auto-session-ipc.d.ts → live/auto-session/ipc.d.ts} +8 -25
  246. package/dist/{session/auto-session-ipc.js → live/auto-session/ipc.js} +36 -161
  247. package/dist/live/auto-session/open-browser.d.ts +6 -0
  248. package/dist/live/auto-session/open-browser.js +47 -0
  249. package/dist/{session/browser.d.ts → live/auto-session/start.d.ts} +1 -2
  250. package/dist/{session/browser.js → live/auto-session/start.js} +2 -3
  251. package/dist/{pilot-overlay → live/pilot}/panel.d.ts +1 -1
  252. package/dist/{pilot-overlay → live/pilot}/panel.js +23 -31
  253. package/dist/{session → live/pilot}/pilot.d.ts +3 -3
  254. package/dist/{session → live/pilot}/pilot.js +5 -4
  255. package/dist/{traverse/run.d.ts → live/traverse/traverse.d.ts} +1 -1
  256. package/dist/live/traverse/traverse.js +212 -0
  257. package/dist/live/traverse/worker.d.ts +37 -0
  258. package/dist/live/traverse/worker.js +200 -0
  259. package/dist/manifest/manifest.d.ts +52 -0
  260. package/dist/manifest/manifest.js +93 -0
  261. package/dist/manifest/map-imports.d.ts +7 -0
  262. package/dist/manifest/map-imports.js +22 -0
  263. package/dist/manifest/maps.d.ts +33 -0
  264. package/dist/manifest/maps.js +62 -0
  265. package/dist/manifest/pack.d.ts +21 -0
  266. package/dist/manifest/pack.js +109 -0
  267. package/dist/manifest/project.d.ts +60 -0
  268. package/dist/manifest/project.js +101 -0
  269. package/dist/{session/block-inject.js → manifest/roots.js} +1 -18
  270. package/dist/manifest/scan.d.ts +19 -0
  271. package/dist/manifest/scan.js +57 -0
  272. package/dist/manifest/source.d.ts +23 -0
  273. package/dist/manifest/source.js +86 -0
  274. package/dist/runner/mode.d.ts +71 -0
  275. package/dist/runner/mode.js +1 -0
  276. package/dist/runner/modes/branches.d.ts +5 -0
  277. package/dist/runner/modes/branches.js +37 -0
  278. package/dist/runner/modes/demo.d.ts +3 -0
  279. package/dist/runner/modes/demo.js +13 -0
  280. package/dist/runner/modes/report.d.ts +2 -0
  281. package/dist/runner/modes/report.js +54 -0
  282. package/dist/runner/modes/run.d.ts +2 -0
  283. package/dist/runner/modes/run.js +3 -0
  284. package/dist/runner/options.d.ts +31 -0
  285. package/dist/runner/options.js +42 -0
  286. package/dist/runner/plan/find.d.ts +18 -0
  287. package/dist/runner/plan/find.js +65 -0
  288. package/dist/runner/plan/plan.d.ts +11 -0
  289. package/dist/runner/plan/plan.js +97 -0
  290. package/dist/runner/plan/seed-mem.d.ts +12 -0
  291. package/dist/runner/plan/seed-mem.js +98 -0
  292. package/dist/runner/plan/spec.d.ts +5 -0
  293. package/dist/runner/plan/spec.js +17 -0
  294. package/dist/runner/play-steps.d.ts +2 -0
  295. package/dist/runner/play-steps.js +59 -0
  296. package/dist/runner/runner.d.ts +4 -0
  297. package/dist/runner/runner.js +64 -0
  298. package/dist/runner/session.d.ts +9 -0
  299. package/dist/runner/session.js +87 -0
  300. package/dist/{browser.js → runtime/browser.js} +4 -2
  301. package/dist/{env-file.js → runtime/env-file.js} +7 -12
  302. package/dist/{extensions.d.ts → runtime/extensions.d.ts} +1 -5
  303. package/dist/{extensions.js → runtime/extensions.js} +2 -1
  304. package/dist/runtime/full-launch.d.ts +1 -0
  305. package/dist/runtime/full-launch.js +34 -0
  306. package/dist/runtime/global-flag.d.ts +5 -0
  307. package/dist/runtime/global-flag.js +18 -0
  308. package/dist/{playwright-config.d.ts → runtime/playwright-config.d.ts} +1 -1
  309. package/dist/{playwright.config.js → runtime/playwright.config.js} +3 -2
  310. package/dist/runtime/run-log.d.ts +2 -0
  311. package/dist/runtime/run-log.js +17 -0
  312. package/dist/{video-dir.js → runtime/video-dir.js} +3 -2
  313. package/dist/{config.d.ts → runtime/waygraph-config.d.ts} +6 -9
  314. package/dist/{config.js → runtime/waygraph-config.js} +21 -51
  315. package/dist/{webserver.js → runtime/webserver.js} +5 -30
  316. package/examples/routed-demo/config/waygraph.config.ts +20 -0
  317. package/examples/routed-demo/package.json +1 -4
  318. package/examples/routed-demo/scripts/fixture-server.mjs +1 -1
  319. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +2 -4
  320. package/examples/routed-demo/src/flows/routed-demo.flow.ts +1 -2
  321. package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +5 -4
  322. package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +3 -3
  323. package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +3 -3
  324. package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +3 -3
  325. package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +3 -3
  326. package/examples/routed-demo/src/states/routed-demo.states.ts +5 -3
  327. package/examples/routed-demo/tests/routed-demo.spec.ts +4 -4
  328. package/examples/routed-demo/tsconfig.json +1 -1
  329. package/examples/saucedemo/docs/CONVENTION.md +4 -5
  330. package/examples/saucedemo/docs/HELPERS.md +11 -11
  331. package/examples/saucedemo/src/blocks/SITE-MAP.md +0 -1
  332. package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +1 -5
  333. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -3
  334. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  335. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  336. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  337. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  338. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  339. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +5 -8
  340. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -3
  341. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  342. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +35 -43
  343. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  344. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  345. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  346. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  347. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  348. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  349. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -4
  350. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -4
  351. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +4 -5
  352. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  353. package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  354. package/examples/saucedemo/src/flows/api-demo.flow.ts +12 -10
  355. package/examples/saucedemo/src/states/checkout.states.ts +21 -11
  356. package/examples/saucedemo/src/stubs/device-showcase.ts +8 -10
  357. package/examples/saucedemo/tests/auto-graph.spec.ts +4 -12
  358. package/package.json +14 -6
  359. package/templates/agents/waygraph-planner.agent.md +2 -2
  360. package/templates/quickstart/docs/CONVENTION.md +4 -4
  361. package/templates/quickstart/docs/HELPERS.md +10 -8
  362. package/templates/quickstart/package.json +0 -3
  363. package/templates/quickstart/src/blocks/SITE-MAP.md +0 -1
  364. package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +1 -5
  365. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -3
  366. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  367. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  368. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  369. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  370. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  371. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +5 -8
  372. package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -3
  373. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  374. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +35 -43
  375. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  376. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  377. package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  378. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  379. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  380. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  381. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -4
  382. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -4
  383. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +4 -5
  384. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  385. package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  386. package/templates/quickstart/src/flows/api-demo.flow.ts +12 -10
  387. package/templates/quickstart/src/states/checkout.states.ts +21 -11
  388. package/templates/quickstart/src/stubs/device-showcase.ts +8 -10
  389. package/templates/scaffold/README.md +2 -1
  390. package/templates/scaffold/STRUCTURE.md +5 -4
  391. package/templates/scaffold/config/waygraph.config.ts +1 -0
  392. package/templates/scaffold/gitignore +1 -0
  393. package/templates/scaffold/src/flows/README.md +2 -2
  394. package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +3 -3
  395. package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +3 -3
  396. package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -4
  397. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +3 -3
  398. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +3 -3
  399. package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +5 -4
  400. package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -4
  401. package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -3
  402. package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +3 -3
  403. package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +4 -4
  404. package/templates/scaffold/src/map/(external)/hoppscotch/_keys.ts +21 -0
  405. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +4 -4
  406. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +4 -4
  407. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +4 -4
  408. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +5 -4
  409. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +6 -5
  410. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +6 -5
  411. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +5 -4
  412. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +6 -5
  413. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +6 -5
  414. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +6 -5
  415. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +6 -5
  416. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +6 -5
  417. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +6 -5
  418. package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +3 -3
  419. package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +3 -3
  420. package/templates/scaffold/src/map/(external)/hoppscotch/_states.ts +6 -0
  421. package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +3 -3
  422. package/templates/scaffold/src/map/(external)/mailpit/_keys.ts +13 -0
  423. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +4 -4
  424. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +4 -4
  425. package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +6 -5
  426. package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +6 -5
  427. package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +3 -3
  428. package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +3 -3
  429. package/templates/scaffold/src/map/(external)/mailpit/_states.ts +9 -0
  430. package/templates/scaffold/src/map/README.md +7 -0
  431. package/templates/scaffold/src/states/README.md +4 -1
  432. package/templates/scaffold/src/states/demo.mem-keys.ts +1 -29
  433. package/templates/scaffold/src/states/demo.states.ts +14 -20
  434. package/templates/scaffold/tests/hoppscotch.spec.ts +1 -11
  435. package/templates/scaffold/tests/mail-verify.spec.ts +2 -2
  436. package/templates/skills/waygraph-blind-pilot.skill.md +2 -6
  437. package/templates/skills/waygraph-convention.skill.md +23 -14
  438. package/templates/skills/waygraph-pilot.skill.md +7 -4
  439. package/dist/auto-session/session.d.ts +0 -193
  440. package/dist/auto-session/session.js +0 -719
  441. package/dist/auto-session/verbose-log.js +0 -16
  442. package/dist/auto-session.d.ts +0 -2
  443. package/dist/auto-session.js +0 -3
  444. package/dist/cli/discover.d.ts +0 -40
  445. package/dist/cli/discover.js +0 -148
  446. package/dist/commands/agent-dive.js +0 -52
  447. package/dist/commands/check.js +0 -192
  448. package/dist/commands/map.js +0 -29
  449. package/dist/commands/run.js +0 -104
  450. package/dist/commands/session.js +0 -600
  451. package/dist/commands/traverse.js +0 -177
  452. package/dist/core/block.d.ts +0 -109
  453. package/dist/core/blocks/effect.js +0 -23
  454. package/dist/core/config.js +0 -17
  455. package/dist/core/engine.d.ts +0 -198
  456. package/dist/core/flow.d.ts +0 -294
  457. package/dist/core/flow.js +0 -432
  458. package/dist/core/map-builder.js +0 -383
  459. package/dist/core.d.ts +0 -14
  460. package/dist/core.js +0 -15
  461. package/dist/highlights/merge.d.ts +0 -8
  462. package/dist/highlights/merge.js +0 -173
  463. package/dist/highlights/run-phase.d.ts +0 -43
  464. package/dist/highlights/stub-ctx.d.ts +0 -10
  465. package/dist/highlights/stub-ctx.js +0 -331
  466. package/dist/highlights/types.d.ts +0 -613
  467. package/dist/highlights.d.ts +0 -9
  468. package/dist/highlights.js +0 -10
  469. package/dist/pilot-overlay.d.ts +0 -5
  470. package/dist/pilot-overlay.js +0 -6
  471. package/dist/runner/banner-log.js +0 -63
  472. package/dist/runner/chain-run.js +0 -102
  473. package/dist/runner/cursor.js +0 -140
  474. package/dist/runner/demo-log.js +0 -316
  475. package/dist/runner/device-stage.d.ts +0 -9
  476. package/dist/runner/device-stage.js +0 -420
  477. package/dist/runner/discovery.js +0 -105
  478. package/dist/runner/index.js +0 -2
  479. package/dist/runner/inpage/banner.d.ts +0 -21
  480. package/dist/runner/inpage/banner.js +0 -156
  481. package/dist/runner/inpage/caption.d.ts +0 -3
  482. package/dist/runner/inpage/caption.js +0 -23
  483. package/dist/runner/inpage/core.d.ts +0 -4
  484. package/dist/runner/inpage/core.js +0 -316
  485. package/dist/runner/inpage/device.d.ts +0 -3
  486. package/dist/runner/inpage/device.js +0 -211
  487. package/dist/runner/inpage/network.d.ts +0 -15
  488. package/dist/runner/inpage/network.js +0 -217
  489. package/dist/runner/inpage/panel-chrome.js +0 -192
  490. package/dist/runner/inpage/stamp.js +0 -46
  491. package/dist/runner/inpage/swipe-zoom.js +0 -220
  492. package/dist/runner/inpage/todos.js +0 -337
  493. package/dist/runner/interaction-patch.js +0 -384
  494. package/dist/runner/main.js +0 -469
  495. package/dist/runner/network-capture.d.ts +0 -9
  496. package/dist/runner/network-capture.js +0 -126
  497. package/dist/runner/overlay-css.d.ts +0 -3
  498. package/dist/runner/overlay-css.js +0 -377
  499. package/dist/runner/overlay-install.js +0 -90
  500. package/dist/runner/overlay-stage.js +0 -110
  501. package/dist/runner/rings.js +0 -514
  502. package/dist/runner/seed-mem.js +0 -110
  503. package/dist/runner/slides.js +0 -278
  504. package/dist/runner/step-mode.js +0 -703
  505. package/dist/runner/step-panels.js +0 -729
  506. package/dist/runner/teardown.js +0 -202
  507. package/dist/runner/todo-dock.js +0 -142
  508. package/dist/session/auto-explore-run.d.ts +0 -40
  509. package/dist/session/auto-explore-run.js +0 -707
  510. package/dist/session/step-overlay.d.ts +0 -37
  511. package/dist/session/step-overlay.js +0 -244
  512. package/dist/traverse/run.js +0 -423
  513. package/examples/routed-demo/playwright.config.ts +0 -21
  514. package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  515. package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  516. /package/dist/{commands → cli/commands}/agent-dive-scaffold.d.ts +0 -0
  517. /package/dist/{commands → cli/commands}/agent-dive.d.ts +0 -0
  518. /package/dist/{commands → cli/commands}/extensions.d.ts +0 -0
  519. /package/dist/{commands → cli/commands}/init.d.ts +0 -0
  520. /package/dist/{commands → cli/commands}/list.d.ts +0 -0
  521. /package/dist/{commands → cli/commands}/map.d.ts +0 -0
  522. /package/dist/{commands → cli/commands}/session.d.ts +0 -0
  523. /package/dist/{commands → cli/commands}/test.d.ts +0 -0
  524. /package/dist/{commands → cli/commands}/traverse.d.ts +0 -0
  525. /package/dist/{commands → cli/commands}/try.d.ts +0 -0
  526. /package/dist/{commands → cli/commands}/upgrade.d.ts +0 -0
  527. /package/dist/{highlights → demo/narration}/shorthand.js +0 -0
  528. /package/dist/{session/overlay-beacon.d.ts → demo/overlay/beacon.d.ts} +0 -0
  529. /package/dist/{session/overlay-beacon.js → demo/overlay/beacon.js} +0 -0
  530. /package/dist/{pilot-overlay/action-ring.d.ts → demo/overlay/pilot/actions.d.ts} +0 -0
  531. /package/dist/{ui → demo/overlay/ui}/components/ring.d.ts +0 -0
  532. /package/dist/{ui → demo/overlay/ui}/stylesheet.d.ts +0 -0
  533. /package/dist/{ui → demo/overlay/ui}/stylesheet.js +0 -0
  534. /package/dist/{ui → demo/overlay/ui}/tokens.d.ts +0 -0
  535. /package/dist/{ui → demo/overlay/ui}/tokens.js +0 -0
  536. /package/dist/{highlights → demo}/types.js +0 -0
  537. /package/dist/{auto-session → demo}/verbose-log.d.ts +0 -0
  538. /package/dist/{selector.d.ts → engine/trait/selector.d.ts} +0 -0
  539. /package/dist/{selector.js → engine/trait/selector.js} +0 -0
  540. /package/dist/{traverse → live/traverse}/coverage.d.ts +0 -0
  541. /package/dist/{traverse → live/traverse}/coverage.js +0 -0
  542. /package/dist/{traverse → live/traverse}/lease.d.ts +0 -0
  543. /package/dist/{traverse → live/traverse}/lease.js +0 -0
  544. /package/dist/{session/block-inject.d.ts → manifest/roots.d.ts} +0 -0
  545. /package/dist/{blocks-select.d.ts → manifest/select.d.ts} +0 -0
  546. /package/dist/{blocks-select.js → manifest/select.js} +0 -0
  547. /package/dist/{browser.d.ts → runtime/browser.d.ts} +0 -0
  548. /package/dist/{env-file.d.ts → runtime/env-file.d.ts} +0 -0
  549. /package/dist/{playwright-config.js → runtime/playwright-config.js} +0 -0
  550. /package/dist/{playwright.config.d.ts → runtime/playwright.config.d.ts} +0 -0
  551. /package/dist/{video-dir.d.ts → runtime/video-dir.d.ts} +0 -0
  552. /package/dist/{webserver.d.ts → runtime/webserver.d.ts} +0 -0
@@ -0,0 +1,57 @@
1
+ // The one place a project's files are walked and imported. Everything that needs the project's Blocks or Flows
2
+ // (graph, check, map, auto, traverse, the runner) goes through here.
3
+ import { readdirSync, statSync } from "node:fs";
4
+ import { join, resolve } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ /** Every file under `dir` whose name matches, skipping `node_modules`, `dist` and `.git`. */
7
+ export function walkDir(dir, pattern) {
8
+ const results = [];
9
+ let entries;
10
+ try {
11
+ entries = readdirSync(dir, { withFileTypes: true });
12
+ }
13
+ catch {
14
+ return results;
15
+ }
16
+ for (const entry of entries) {
17
+ const full = join(dir, entry.name);
18
+ if (entry.isDirectory()) {
19
+ if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git")
20
+ continue;
21
+ results.push(...walkDir(full, pattern));
22
+ }
23
+ else if (pattern.test(entry.name)) {
24
+ results.push(full);
25
+ }
26
+ }
27
+ return results;
28
+ }
29
+ /**
30
+ * Imports a project file. The file's mtime is part of the URL: Node caches an ESM import per specifier for the life of the
31
+ * process, so a long-running session reloading an edited Block would otherwise keep the first version.
32
+ */
33
+ export async function importFresh(filePath) {
34
+ const resolved = resolve(filePath);
35
+ const url = pathToFileURL(resolved);
36
+ url.searchParams.set("t", String(statSync(resolved).mtimeMs));
37
+ return (await import(url.href));
38
+ }
39
+ export function isBlockLike(val) {
40
+ if (val === null || typeof val !== "object")
41
+ return false;
42
+ const obj = val;
43
+ if (typeof obj.name !== "string")
44
+ return false;
45
+ const instruction = obj.instruction;
46
+ return instruction !== null && typeof instruction === "object" && typeof instruction?.act === "function";
47
+ }
48
+ export function isFlowLike(val) {
49
+ return (val !== null &&
50
+ typeof val === "object" &&
51
+ typeof val.run === "function" &&
52
+ typeof val.blocks === "function");
53
+ }
54
+ /** The factory kind a Block was built with (`nav`, `page`, `assert`), or undefined for Methods and Effects. */
55
+ export function blockKind(block) {
56
+ return block.__waygraphKind;
57
+ }
@@ -0,0 +1,23 @@
1
+ import type { SourceFile } from "ts-morph";
2
+ /** The file as it is on disk now. */
3
+ export declare function parseSource(file: string): SourceFile;
4
+ /** Names the file exports: `export const|let|var|function|class X`, and `export { X }`. */
5
+ export declare function exportedNames(sf: SourceFile): string[];
6
+ /** Every module the file imports or re-exports from, including dynamic `import("x")`. */
7
+ export declare function importSpecifiers(sf: SourceFile): string[];
8
+ /** Names imported from modules whose specifier passes `from`, in source order (the imported name, not an alias). */
9
+ export declare function namedImportsFrom(sf: SourceFile, from: (specifier: string) => boolean): string[];
10
+ /** The string literal at `argIndex` of every call whose callee text passes `callee`, in source order. */
11
+ export declare function stringArgs(sf: SourceFile, callee: (text: string) => boolean, argIndex?: number): string[];
12
+ /** A string property of the object literal passed to every matching call: `Trait.url({ pathname: "/x" })` -> "/x". */
13
+ export declare function objectArgProperty(sf: SourceFile, callee: (text: string) => boolean, property: string): string[];
14
+ /** Every string literal in the file (comments are not strings), with the property name it initializes, if any. */
15
+ export declare function stringLiterals(sf: SourceFile): {
16
+ value: string;
17
+ property: string | undefined;
18
+ }[];
19
+ /** Every call in the file (comments and strings are not calls): its callee as written and whether its first argument is a string. */
20
+ export declare function calls(sf: SourceFile): {
21
+ callee: string;
22
+ literalFirstArg: boolean;
23
+ }[];
@@ -0,0 +1,86 @@
1
+ // Reads a TypeScript file's shape (its exports, imports, string arguments) from the AST (ts-morph), for the places that
2
+ // need it without importing the file: `list`, `nav`, a flow file's export name, a map group's imports.
3
+ import { readFileSync } from "node:fs";
4
+ import { Node, Project, SyntaxKind } from "ts-morph";
5
+ const project = new Project({ useInMemoryFileSystem: true, skipFileDependencyResolution: true });
6
+ /** The file as it is on disk now. */
7
+ export function parseSource(file) {
8
+ return project.createSourceFile(file.replace(/\\/g, "/").replace(/^[A-Za-z]:/, ""), readFileSync(file, "utf8"), { overwrite: true });
9
+ }
10
+ /** Names the file exports: `export const|let|var|function|class X`, and `export { X }`. */
11
+ export function exportedNames(sf) {
12
+ const names = [];
13
+ for (const statement of sf.getStatements()) {
14
+ if (Node.isVariableStatement(statement) && statement.isExported())
15
+ names.push(...statement.getDeclarations().map((d) => d.getName()));
16
+ else if ((Node.isFunctionDeclaration(statement) || Node.isClassDeclaration(statement)) && statement.isExported() && statement.getName())
17
+ names.push(statement.getName());
18
+ else if (Node.isExportDeclaration(statement) && !statement.getModuleSpecifier())
19
+ names.push(...statement.getNamedExports().map((e) => e.getAliasNode()?.getText() ?? e.getName()));
20
+ }
21
+ return names;
22
+ }
23
+ /** Every module the file imports or re-exports from, including dynamic `import("x")`. */
24
+ export function importSpecifiers(sf) {
25
+ const specs = [
26
+ ...sf.getImportDeclarations().map((d) => d.getModuleSpecifierValue()),
27
+ ...sf.getExportDeclarations().flatMap((d) => d.getModuleSpecifierValue() ?? []),
28
+ ];
29
+ for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression)) {
30
+ const arg = call.getArguments()[0];
31
+ if (call.getExpression().getKind() === SyntaxKind.ImportKeyword && Node.isStringLiteral(arg))
32
+ specs.push(arg.getLiteralValue());
33
+ }
34
+ return specs;
35
+ }
36
+ /** Names imported from modules whose specifier passes `from`, in source order (the imported name, not an alias). */
37
+ export function namedImportsFrom(sf, from) {
38
+ return sf
39
+ .getImportDeclarations()
40
+ .filter((d) => from(d.getModuleSpecifierValue()))
41
+ .flatMap((d) => d.getNamedImports().map((n) => n.getName()));
42
+ }
43
+ /** The string literal at `argIndex` of every call whose callee text passes `callee`, in source order. */
44
+ export function stringArgs(sf, callee, argIndex = 0) {
45
+ const out = [];
46
+ for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression)) {
47
+ if (!callee(call.getExpression().getText()))
48
+ continue;
49
+ const arg = call.getArguments()[argIndex];
50
+ if (Node.isStringLiteral(arg) || Node.isNoSubstitutionTemplateLiteral(arg))
51
+ out.push(arg.getLiteralValue());
52
+ }
53
+ return out;
54
+ }
55
+ /** A string property of the object literal passed to every matching call: `Trait.url({ pathname: "/x" })` -> "/x". */
56
+ export function objectArgProperty(sf, callee, property) {
57
+ const out = [];
58
+ for (const call of sf.getDescendantsOfKind(SyntaxKind.CallExpression)) {
59
+ if (!callee(call.getExpression().getText()))
60
+ continue;
61
+ const arg = call.getArguments()[0];
62
+ const prop = Node.isObjectLiteralExpression(arg) ? arg.getProperty(property) : undefined;
63
+ const value = Node.isPropertyAssignment(prop) ? prop.getInitializer() : undefined;
64
+ if (Node.isStringLiteral(value) || Node.isNoSubstitutionTemplateLiteral(value))
65
+ out.push(value.getLiteralValue());
66
+ }
67
+ return out;
68
+ }
69
+ /** Every string literal in the file (comments are not strings), with the property name it initializes, if any. */
70
+ export function stringLiterals(sf) {
71
+ const out = [];
72
+ for (const node of [...sf.getDescendantsOfKind(SyntaxKind.StringLiteral), ...sf.getDescendantsOfKind(SyntaxKind.NoSubstitutionTemplateLiteral)]) {
73
+ const parent = node.getParent();
74
+ if (Node.isImportDeclaration(parent) || Node.isExportDeclaration(parent))
75
+ continue;
76
+ out.push({ value: node.getLiteralValue(), property: Node.isPropertyAssignment(parent) && parent.getInitializer() === node ? parent.getName() : undefined });
77
+ }
78
+ return out;
79
+ }
80
+ /** Every call in the file (comments and strings are not calls): its callee as written and whether its first argument is a string. */
81
+ export function calls(sf) {
82
+ return sf.getDescendantsOfKind(SyntaxKind.CallExpression).map((call) => {
83
+ const arg = call.getArguments()[0];
84
+ return { callee: call.getExpression().getText(), literalFirstArg: Node.isStringLiteral(arg) || Node.isTemplateExpression(arg) || Node.isNoSubstitutionTemplateLiteral(arg) };
85
+ });
86
+ }
@@ -0,0 +1,71 @@
1
+ import type { BrowserContext } from "@playwright/test";
2
+ import type { Checkpoint } from "../engine/checkpoint/checkpoint.js";
3
+ import type { EngineConfig } from "../engine/config.js";
4
+ import type { MemPage } from "../engine/mem/mem.js";
5
+ import type { DemoPace } from "../engine/stub/pace.js";
6
+ import type { HighlightStyleDefaults } from "../engine/stub/ring.js";
7
+ import type { WgPage } from "../demo/types.js";
8
+ import type { SomeBlock } from "../engine/block/block.js";
9
+ /** One Block to play, with what its flow says about it. */
10
+ export interface PlayStep {
11
+ block: SomeBlock;
12
+ exportName: string;
13
+ /** The engine config of the flow it came from (its layouts apply when it runs). */
14
+ config: EngineConfig;
15
+ /** Set on a named flow's steps; ad hoc Block chains have no episodes. */
16
+ episodeNumber?: number | undefined;
17
+ episodeTitle?: string | undefined;
18
+ /** Clear cookies and storage before this step (a flow with `sessionReset`, chained after another). */
19
+ resetSession: boolean;
20
+ /** Seeds this segment's `--data` into mem; set on a segment's first step. */
21
+ seedMem?: (() => void) | undefined;
22
+ /** Set on a flow's last step when the flow is meant to fail (`map({ expectedFailure })`). */
23
+ expectedFailureReason?: string | undefined;
24
+ demoPace?: DemoPace | undefined;
25
+ highlightStyle?: HighlightStyleDefaults | undefined;
26
+ /** An inner step of an expanded fast-forward unit (`--ff-expand`). */
27
+ wasFastForward?: boolean | undefined;
28
+ ffSource?: string | undefined;
29
+ }
30
+ /** The browser everything plays in. */
31
+ export interface PlaySession {
32
+ context: BrowserContext;
33
+ page: WgPage;
34
+ mem: MemPage;
35
+ baseURL: string | undefined;
36
+ }
37
+ /** How a step ended, for a mode's `failed` hook: it threw, or it landed on the branch its flow expects to fail on. */
38
+ export type StepFailure = {
39
+ error: unknown;
40
+ result?: undefined;
41
+ } | {
42
+ error?: undefined;
43
+ result: Checkpoint<string>;
44
+ };
45
+ export interface PlayOutcome {
46
+ ok: boolean;
47
+ result?: Checkpoint<string> | undefined;
48
+ /** The step that failed, when one did. */
49
+ failedAt?: {
50
+ index: number;
51
+ step: PlayStep;
52
+ error: unknown;
53
+ } | undefined;
54
+ /** Set when the run stopped where its flow expects to fail. */
55
+ expectedFailure?: {
56
+ step: PlayStep;
57
+ reason: string;
58
+ } | undefined;
59
+ }
60
+ /** A way of playing steps. Every hook is optional; with none, it is a plain Playwright run. */
61
+ export interface Mode {
62
+ name: string;
63
+ begin?(steps: readonly PlayStep[]): Promise<void>;
64
+ /** After the page was reset between episodes. */
65
+ afterReset?(): Promise<void>;
66
+ before?(index: number): Promise<void>;
67
+ after?(index: number, result: Checkpoint<string>, ms: number): Promise<void>;
68
+ /** A step failed (or reached its expected failure): retry its episode, or stop. Without the hook: stop. */
69
+ failed?(index: number, failure: StepFailure, ms: number): Promise<"retry" | "stop">;
70
+ end?(outcome: PlayOutcome): Promise<void>;
71
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { MemPage } from "../../engine/mem/mem.js";
2
+ import type { Flow } from "../../engine/flow/flow.js";
3
+ import type { PlayOptions } from "../options.js";
4
+ import type { Checkpoint } from "../../engine/checkpoint/checkpoint.js";
5
+ export declare function playBranches(flows: readonly Flow<Checkpoint<string>>[], mem: MemPage, options: PlayOptions): Promise<void>;
@@ -0,0 +1,37 @@
1
+ import { branchRoutes, runBranchRegression } from "../../engine/flow/branch-regression.js";
2
+ import { extensionPathsFromEnv } from "../../runtime/browser.js";
3
+ export async function playBranches(flows, mem, options) {
4
+ const flow = flows.length === 1 ? flows[0] : undefined;
5
+ if (!flow) {
6
+ console.error("waygraph run --all-branches: needs a single Flow reference (e.g. --blocks loginFlow), not a multi-segment chain spec - nothing else has one branch tree to explore.");
7
+ process.exitCode = 1;
8
+ return;
9
+ }
10
+ if (!branchRoutes(flow)) {
11
+ console.error("waygraph run --all-branches: this Flow was not built with MapBuilder.branch() - there is no branch tree to explore. Run it normally instead.");
12
+ process.exitCode = 1;
13
+ return;
14
+ }
15
+ if (extensionPathsFromEnv().length > 0) {
16
+ console.warn("waygraph run --all-branches: extensions are not loaded (branches run in cloned contexts)");
17
+ }
18
+ const { chromium } = await import("@playwright/test");
19
+ const browser = await chromium.launch({ headless: !options.headed });
20
+ try {
21
+ const context = await browser.newContext(options.baseURL ? { baseURL: options.baseURL } : undefined);
22
+ const results = await runBranchRegression(flow, context, mem, { cloneSession: !options.sharedSession });
23
+ for (const r of results) {
24
+ console.log(`waygraph run --all-branches: ${r.path || "(root)"} -> ${r.status}` +
25
+ (r.result ? ` (${JSON.stringify(r.result)})` : "") +
26
+ (r.error ? ` - ${r.error}` : ""));
27
+ }
28
+ const failed = results.filter((r) => r.status === "failed");
29
+ if (failed.length) {
30
+ console.error(`waygraph run --all-branches: ${failed.length}/${results.length} path(s) failed`);
31
+ process.exitCode = 1;
32
+ }
33
+ }
34
+ finally {
35
+ await browser.close();
36
+ }
37
+ }
@@ -0,0 +1,3 @@
1
+ import type { Mode, PlaySession, PlayStep } from "../mode.js";
2
+ import type { PlayOptions } from "../options.js";
3
+ export declare function demoMode(session: PlaySession, steps: readonly PlayStep[], options: PlayOptions, beat: number): Promise<Mode>;
@@ -0,0 +1,13 @@
1
+ // `waygraph demo`: the same steps, with the waygraph UI around each one (src/demo/stepper/).
2
+ import { createStepper } from "../../demo/stepper/stepper.js";
3
+ export async function demoMode(session, steps, options, beat) {
4
+ const stepper = await createStepper(session.page, session.mem, steps, { title: options.title, fastBlocks: options.fastBlocks, beat });
5
+ return {
6
+ name: "demo",
7
+ afterReset: stepper.afterReset,
8
+ before: stepper.before,
9
+ after: (index, result) => stepper.after(index, result),
10
+ failed: (index, failure) => stepper.failed(index, failure),
11
+ end: () => stepper.end(),
12
+ };
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { Mode, PlaySession } from "../mode.js";
2
+ export declare function reportMode(session: PlaySession): Mode;
@@ -0,0 +1,54 @@
1
+ // `waygraph run` with WAYGRAPH_JSON=1: plays like `run` and prints one JSON report (each step's Checkpoint and time,
2
+ // a screenshot on failure). `runId` names the matching `.waygraph/runs/<runId>.jsonl`.
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { currentRunId, recordArtifact } from "../../engine/run/events.js";
6
+ export function reportMode(session) {
7
+ let steps = [];
8
+ const done = [];
9
+ let screenshot = null;
10
+ const message = (error) => (error instanceof Error ? error.message : String(error));
11
+ return {
12
+ name: "report",
13
+ async begin(all) {
14
+ steps = all;
15
+ },
16
+ async after(index, result, ms) {
17
+ done.push({ name: steps[index].block.name, checkpoint: result, ms });
18
+ },
19
+ async failed(index, failure, ms) {
20
+ const step = steps[index];
21
+ if (failure.result) {
22
+ done.push({ name: step.block.name, checkpoint: failure.result, ms });
23
+ }
24
+ else if (step.expectedFailureReason) {
25
+ done.push({ name: step.block.name, expectedFailure: true, error: message(failure.error), ms });
26
+ }
27
+ else {
28
+ screenshot = join(tmpdir(), "waygraph-chain-failure-" + Date.now() + ".png");
29
+ await session.page.screenshot({ path: screenshot, fullPage: true }).then(() => recordArtifact("screenshot", screenshot), () => (screenshot = null));
30
+ }
31
+ return "stop";
32
+ },
33
+ async end(outcome) {
34
+ const runId = currentRunId();
35
+ const report = outcome.failedAt
36
+ ? {
37
+ runId,
38
+ ok: false,
39
+ failedAt: outcome.failedAt.step.block.name,
40
+ stepIndex: outcome.failedAt.index,
41
+ totalSteps: steps.length,
42
+ error: message(outcome.failedAt.error),
43
+ steps: done,
44
+ screenshot,
45
+ }
46
+ : outcome.expectedFailure && outcome.result === undefined
47
+ ? { runId, ok: true, expectedFailure: true, failedAt: outcome.expectedFailure.step.block.name, reason: outcome.expectedFailure.reason, steps: done }
48
+ : { runId, ok: true, result: done.length > 0 ? done[done.length - 1].checkpoint : null, steps: done };
49
+ console.log(JSON.stringify(report, null, 2));
50
+ if (!report.ok)
51
+ process.exitCode = 1;
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,2 @@
1
+ import type { Mode } from "../mode.js";
2
+ export declare function runMode(): Mode;
@@ -0,0 +1,3 @@
1
+ export function runMode() {
2
+ return { name: "run" };
3
+ }
@@ -0,0 +1,31 @@
1
+ import type { PlayStep } from "./mode.js";
2
+ export type ModeName = "run" | "demo" | "report" | "branches";
3
+ export interface PlayOptions {
4
+ mode: ModeName;
5
+ headed: boolean;
6
+ baseURL: string | undefined;
7
+ title: string | undefined;
8
+ /** Block names that skip the demo's added dwell (WAYGRAPH_FAST_BLOCKS). */
9
+ fastBlocks: Set<string>;
10
+ /** Clear the session before every step after the first (WAYGRAPH_CLEAR_SESSION). */
11
+ clearSession: boolean;
12
+ /** Record a video: the folder, or "1" for the default one. */
13
+ video: string | undefined;
14
+ videoViewport: string | undefined;
15
+ /** Expand fast-forward units into their inner steps (--ff-expand / --ff-disabled). */
16
+ ffExpand: boolean;
17
+ ffDisabled: boolean;
18
+ /** Fill missing `requires` from registerMemStub for every flow (--mem-stub). */
19
+ memStub: boolean;
20
+ /** --all-branches without cloning the session per branch. */
21
+ sharedSession: boolean;
22
+ }
23
+ export declare function readOptions(): PlayOptions;
24
+ /**
25
+ * The slowMo for the browser launch and the demo's own beat after each action. The demo launches at 0 and paces
26
+ * itself, so a step's pace can remove the beat; a fast-forward unit in the steps drops the beat to 0.
27
+ */
28
+ export declare function slowMoFor(options: PlayOptions, steps: readonly PlayStep[]): {
29
+ launch: number | undefined;
30
+ demoBeat: number;
31
+ };
@@ -0,0 +1,42 @@
1
+ // How to play, read once from the environment the CLI set (flags beat the config file, which beats these defaults).
2
+ import { envFlag, envNumber, envString, envSwitch } from "../engine/env.js";
3
+ function readMode() {
4
+ if (envFlag("WAYGRAPH_ALL_BRANCHES"))
5
+ return "branches";
6
+ if (envFlag("WAYGRAPH_JSON"))
7
+ return "report";
8
+ return envFlag("WAYGRAPH_STEP") ? "demo" : "run";
9
+ }
10
+ export function readOptions() {
11
+ const mode = readMode();
12
+ return {
13
+ mode,
14
+ // A manual demo is watched, so it is headed by default; WAYGRAPH_HEADED=0 (e.g. --auto-play-video) still wins.
15
+ headed: envSwitch("WAYGRAPH_HEADED", mode === "demo"),
16
+ baseURL: envString("WAYGRAPH_BASE_URL"),
17
+ title: envString("WAYGRAPH_TITLE"),
18
+ fastBlocks: new Set((envString("WAYGRAPH_FAST_BLOCKS") || "").split(",").map((s) => s.trim()).filter(Boolean)),
19
+ clearSession: envFlag("WAYGRAPH_CLEAR_SESSION"),
20
+ video: envString("WAYGRAPH_VIDEO"),
21
+ videoViewport: envString("WAYGRAPH_VIDEO_VIEWPORT"),
22
+ ffExpand: envFlag("WAYGRAPH_FF_EXPAND") || envFlag("WAYGRAPH_FF_DISABLED"),
23
+ ffDisabled: envFlag("WAYGRAPH_FF_DISABLED"),
24
+ memStub: envFlag("WAYGRAPH_MEM_STUB"),
25
+ sharedSession: envFlag("WAYGRAPH_SHARED_SESSION"),
26
+ };
27
+ }
28
+ /**
29
+ * The slowMo for the browser launch and the demo's own beat after each action. The demo launches at 0 and paces
30
+ * itself, so a step's pace can remove the beat; a fast-forward unit in the steps drops the beat to 0.
31
+ */
32
+ export function slowMoFor(options, steps) {
33
+ const demo = options.mode === "demo";
34
+ const hasFastForward = steps.some((s) => s.block.fastForward === true || s.wasFastForward === true);
35
+ const slowMo = envNumber("WAYGRAPH_SLOWMO") ?? (demo ? (hasFastForward ? 0 : 350) : undefined);
36
+ if (demo && hasFastForward && envNumber("WAYGRAPH_SLOWMO") === undefined) {
37
+ console.error(options.ffDisabled
38
+ ? "waygraph demo: --ff-disabled (expanded) -> Playwright slowMo=0 on former FF steps (blitz; same acts as opaque FF)"
39
+ : "waygraph demo: opaque FFCompose in flow -> Playwright slowMo=0 (blitz); set WAYGRAPH_SLOWMO to override");
40
+ }
41
+ return { launch: demo ? 0 : slowMo, demoBeat: slowMo ?? 0 };
42
+ }
@@ -0,0 +1,18 @@
1
+ import type { AnyBlock } from "../../manifest/scan.js";
2
+ import type { Flow } from "../../engine/flow/flow.js";
3
+ import type { Checkpoint } from "../../engine/checkpoint/checkpoint.js";
4
+ export interface FoundBlock {
5
+ block: AnyBlock;
6
+ exportName: string;
7
+ file: string;
8
+ }
9
+ export declare function findBlock(projectDir: string, ref: string): Promise<FoundBlock>;
10
+ /**
11
+ * Finds an already-defined Flow by its export name (e.g. loginFlow) among
12
+ * the project's *.flow.ts files - "I already have this wired up, just point
13
+ * the stepper at it, no chain spec to hand-write." Flows have no runtime
14
+ * .name of their own (unlike Blocks), so this only matches by export
15
+ * identifier. Returns null (not a throw) when nothing matches - the caller
16
+ * falls back to ordinary block-chain spec parsing.
17
+ */
18
+ export declare function findFlow(projectDir: string, flowName: string): Promise<Flow<Checkpoint<string>> | null>;
@@ -0,0 +1,65 @@
1
+ // Finds a Block or Flow in the project (and its installed map packages) by export name or Block name.
2
+ import { relative } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import { isBlockLike, walkDir } from "../../manifest/scan.js";
5
+ /** A built Flow: what `map().end()` returns. */
6
+ function isFlow(val) {
7
+ return val !== null && typeof val === "object" && typeof val.run === "function" && typeof val.blocks === "function";
8
+ }
9
+ import { installedMapPackages, mapPackageBlockFiles } from "../../manifest/maps.js";
10
+ import { reportImportError } from "../../manifest/project.js";
11
+ export async function findBlock(projectDir, ref) {
12
+ const files = [...walkDir(projectDir, /\.block\.ts$/), ...installedMapPackages(projectDir).flatMap(mapPackageBlockFiles)];
13
+ const byRuntimeName = [];
14
+ for (const file of files) {
15
+ let mod;
16
+ try {
17
+ mod = await import(pathToFileURL(file).href);
18
+ }
19
+ catch (err) {
20
+ reportImportError(relative(projectDir, file), err);
21
+ continue;
22
+ }
23
+ for (const [exportName, exported] of Object.entries(mod)) {
24
+ if (!isBlockLike(exported))
25
+ continue;
26
+ if (exportName === ref)
27
+ return { block: exported, exportName, file };
28
+ if (exported.name === ref)
29
+ byRuntimeName.push({ block: exported, exportName, file });
30
+ }
31
+ }
32
+ if (byRuntimeName.length === 1)
33
+ return byRuntimeName[0];
34
+ if (byRuntimeName.length > 1) {
35
+ throw new Error("waygraph chain: \"" + ref + "\" matches " + byRuntimeName.length + " Blocks by name - " +
36
+ byRuntimeName.map((b) => b.exportName + " (" + b.file + ")").join(", ") +
37
+ ". Use the export name to disambiguate.");
38
+ }
39
+ throw new Error("waygraph chain: no Block named \"" + ref + "\" found under " + projectDir);
40
+ }
41
+ /**
42
+ * Finds an already-defined Flow by its export name (e.g. loginFlow) among
43
+ * the project's *.flow.ts files - "I already have this wired up, just point
44
+ * the stepper at it, no chain spec to hand-write." Flows have no runtime
45
+ * .name of their own (unlike Blocks), so this only matches by export
46
+ * identifier. Returns null (not a throw) when nothing matches - the caller
47
+ * falls back to ordinary block-chain spec parsing.
48
+ */
49
+ export async function findFlow(projectDir, flowName) {
50
+ const files = walkDir(projectDir, /\.flow\.ts$/);
51
+ for (const file of files) {
52
+ let mod;
53
+ try {
54
+ mod = await import(pathToFileURL(file).href);
55
+ }
56
+ catch (err) {
57
+ reportImportError(relative(projectDir, file), err);
58
+ continue;
59
+ }
60
+ const candidate = mod[flowName];
61
+ if (isFlow(candidate))
62
+ return candidate;
63
+ }
64
+ return null;
65
+ }
@@ -0,0 +1,11 @@
1
+ import type { MemPage } from "../../engine/mem/mem.js";
2
+ import type { Flow } from "../../engine/flow/flow.js";
3
+ import type { PlayStep } from "../mode.js";
4
+ import type { PlayOptions } from "../options.js";
5
+ import type { Checkpoint } from "../../engine/checkpoint/checkpoint.js";
6
+ export interface Plan {
7
+ steps: PlayStep[];
8
+ /** One Flow per segment (`--all-branches` needs exactly one). */
9
+ flows: Flow<Checkpoint<string>>[];
10
+ }
11
+ export declare function planSteps(projectDir: string, spec: string, mem: MemPage, options: PlayOptions): Promise<Plan>;
@@ -0,0 +1,97 @@
1
+ import { buildFlow, chainFlow } from "../../engine/flow/flow.js";
2
+ import { isFastForwardBlock } from "../../engine/block/compose.js";
3
+ import { findBlock, findFlow } from "./find.js";
4
+ import { seedMemForBlock, seedMemForFlow } from "./seed-mem.js";
5
+ import { parseChainSpec } from "./spec.js";
6
+ export async function planSteps(projectDir, spec, mem, options) {
7
+ const bareFlow = await findBareFlow(projectDir, spec);
8
+ const segments = bareFlow
9
+ ? [flowSegment(bareFlow, spec.trim(), undefined, mem, options)]
10
+ : await Promise.all(parseSegments(spec).map((seg) => resolveSegment(projectDir, seg, mem, options)));
11
+ const steps = stepsOf(segments, options, { episodes: !bareFlow });
12
+ if (options.mode !== "report")
13
+ announce(spec, steps, !!bareFlow, options);
14
+ return { steps, flows: segments.map((s) => s.flow) };
15
+ }
16
+ /** A spec that is just a name might be an existing Flow (`cartFlow`); then no chain spec is needed. */
17
+ async function findBareFlow(projectDir, spec) {
18
+ const ref = spec.trim();
19
+ if (!/^[A-Za-z_$][\w]*$/.test(ref))
20
+ return undefined;
21
+ const flow = await findFlow(projectDir, ref);
22
+ return flow && typeof flow.blocks === "function" ? flow : undefined;
23
+ }
24
+ function parseSegments(spec) {
25
+ const segments = parseChainSpec(spec);
26
+ if (segments.length === 0)
27
+ throw new Error("waygraph chain: empty spec - give at least one block name");
28
+ return segments;
29
+ }
30
+ async function resolveSegment(projectDir, seg, mem, options) {
31
+ const flow = await findFlow(projectDir, seg.ref);
32
+ if (flow && typeof flow.blocks === "function")
33
+ return flowSegment(flow, seg.ref, seg.json, mem, options);
34
+ const found = await findBlock(projectDir, seg.ref);
35
+ if (!found)
36
+ throw new Error(`waygraph: no Block or Flow named "${seg.ref}"`);
37
+ return {
38
+ flow: buildFlow([found.block], {}),
39
+ ref: seg.ref,
40
+ named: false,
41
+ // A bare Block has no map({ memStub }) to opt in; only --mem-stub fills its keys.
42
+ seedMem: () => seedMemForBlock(mem, found, seg.json, options.memStub),
43
+ };
44
+ }
45
+ function flowSegment(flow, ref, json, mem, options) {
46
+ // seeded when the segment starts, not now: two segments may give the same key different values
47
+ const seedMem = () => seedMemForFlow(mem, flow.blocks(), json, ref, flow.memStub === true || options.memStub);
48
+ return { flow, ref, named: true, seedMem };
49
+ }
50
+ /** A fast-forward unit is one step, unless --ff-expand plays its inner Blocks one by one. */
51
+ function expand(infos, options) {
52
+ if (!options.ffExpand)
53
+ return [...infos];
54
+ return infos.flatMap((info) => isFastForwardBlock(info.block)
55
+ ? info.block.steps().map((inner) => ({
56
+ ...inner,
57
+ ...(info.resetSessionBefore ? { resetSessionBefore: true } : {}),
58
+ wasFastForward: true,
59
+ ffSource: info.block.name,
60
+ }))
61
+ : [info]);
62
+ }
63
+ function stepsOf(segments, options, { episodes }) {
64
+ // chainFlow marks each segment's first Block when that segment wants a fresh session.
65
+ const resets = new Set(chainFlow(...segments.map((s) => s.flow)).blocks().filter((b) => b.resetSessionBefore).map((b) => b.block));
66
+ let episode = 0;
67
+ return segments.flatMap((segment) => {
68
+ const episodeNumber = episodes && segment.named ? ++episode : undefined;
69
+ const infos = expand(segment.flow.blocks(), options);
70
+ return infos.map((info, i) => ({
71
+ block: info.block,
72
+ exportName: info.name,
73
+ config: segment.flow.config,
74
+ episodeNumber,
75
+ episodeTitle: episodeNumber === undefined ? undefined : segment.ref,
76
+ resetSession: i === 0 && resets.has(segment.flow.blocks()[0]?.block),
77
+ seedMem: i === 0 ? segment.seedMem : undefined,
78
+ expectedFailureReason: i === infos.length - 1 ? segment.flow.expectedFailureReason : undefined,
79
+ demoPace: segment.flow.demoPace,
80
+ highlightStyle: segment.flow.highlightStyle,
81
+ ...(info.wasFastForward ? { wasFastForward: true, ffSource: info.ffSource } : {}),
82
+ }));
83
+ });
84
+ }
85
+ function announce(spec, steps, bare, options) {
86
+ const names = steps.map((s) => s.block.name).join(" -> ");
87
+ const count = steps.length + " block" + (steps.length === 1 ? "" : "s");
88
+ if (bare) {
89
+ console.log(`waygraph: running existing flow "${spec.trim()}" - ${names} (${count}, no chain spec needed)`);
90
+ if (options.ffDisabled) {
91
+ console.error("waygraph demo: --ff-disabled - FFCompose expanded to inners (dispute / step locus); blitz pacing kept on former FF steps");
92
+ }
93
+ }
94
+ else {
95
+ console.log(`waygraph: chaining ${names} (${count})`);
96
+ }
97
+ }