waygraph 0.15.53 → 0.16.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 (556) 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 +13 -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/{commands → cli/commands}/check.d.ts +0 -1
  21. package/dist/cli/commands/check.js +104 -0
  22. package/dist/cli/commands/codemod-checkpoints.d.ts +18 -0
  23. package/dist/cli/commands/codemod-checkpoints.js +186 -0
  24. package/dist/cli/commands/codemod-flows.d.ts +18 -0
  25. package/dist/cli/commands/codemod-flows.js +284 -0
  26. package/dist/cli/commands/codemod-stubs.d.ts +10 -0
  27. package/dist/cli/commands/codemod-stubs.js +187 -0
  28. package/dist/{commands → cli/commands}/extensions.js +5 -4
  29. package/dist/{commands → cli/commands}/init.js +1 -2
  30. package/dist/{commands → cli/commands}/list.js +9 -7
  31. package/dist/cli/commands/manifest.d.ts +2 -0
  32. package/dist/cli/commands/manifest.js +20 -0
  33. package/dist/cli/commands/map.js +57 -0
  34. package/dist/{commands → cli/commands}/run.d.ts +0 -1
  35. package/dist/cli/commands/run.js +64 -0
  36. package/dist/{commands → cli/commands}/session.js +61 -88
  37. package/dist/{commands → cli/commands}/test.js +11 -14
  38. package/dist/cli/commands/traverse.js +105 -0
  39. package/dist/{commands → cli/commands}/try.js +29 -25
  40. package/dist/{commands → cli/commands}/upgrade.js +40 -4
  41. package/dist/cli/flags.d.ts +193 -16
  42. package/dist/cli/flags.js +179 -234
  43. package/dist/cli/run-chain.d.ts +1 -0
  44. package/dist/cli/run-chain.js +42 -7
  45. package/dist/cli/usage.d.ts +1 -1
  46. package/dist/cli/usage.js +21 -53
  47. package/dist/cli/util.d.ts +2 -2
  48. package/dist/cli/util.js +2 -3
  49. package/dist/{highlights → demo/narration}/css.d.ts +1 -1
  50. package/dist/{highlights → demo/narration}/css.js +2 -3
  51. package/dist/{highlights → demo/narration}/demo-pace.d.ts +7 -11
  52. package/dist/{highlights → demo/narration}/demo-pace.js +9 -11
  53. package/dist/{highlights → demo/narration}/device.d.ts +4 -2
  54. package/dist/{highlights → demo/narration}/device.js +3 -1
  55. package/dist/demo/narration/merge.d.ts +8 -0
  56. package/dist/demo/narration/merge.js +71 -0
  57. package/dist/{highlights/run-phase.d.ts → demo/narration/narration.d.ts} +10 -14
  58. package/dist/{highlights/run-phase.js → demo/narration/narration.js} +25 -94
  59. package/dist/{highlights → demo/narration}/shorthand.d.ts +1 -1
  60. package/dist/demo/narration/stub-ctx.d.ts +8 -0
  61. package/dist/demo/narration/stub-ctx.js +164 -0
  62. package/dist/{highlights → demo/narration}/style.d.ts +1 -7
  63. package/dist/{highlights → demo/narration}/style.js +1 -41
  64. package/dist/{highlights → demo/narration}/todo-dock.d.ts +3 -3
  65. package/dist/{highlights → demo/narration}/todo-dock.js +13 -30
  66. package/dist/demo/overlay/auto-chrome.d.ts +7 -0
  67. package/dist/demo/overlay/auto-chrome.js +97 -0
  68. package/dist/{session/overlay-beacon.d.ts → demo/overlay/beacon.d.ts} +7 -0
  69. package/dist/{session/overlay-beacon.js → demo/overlay/beacon.js} +5 -0
  70. package/dist/demo/overlay/cursor.d.ts +12 -0
  71. package/dist/demo/overlay/cursor.js +142 -0
  72. package/dist/demo/overlay/device-stage.d.ts +13 -0
  73. package/dist/demo/overlay/device-stage.js +396 -0
  74. package/dist/demo/overlay/inpage/banner.d.ts +1 -0
  75. package/dist/demo/overlay/inpage/banner.js +160 -0
  76. package/dist/demo/overlay/inpage/caption.d.ts +2 -0
  77. package/dist/demo/overlay/inpage/caption.js +24 -0
  78. package/dist/demo/overlay/inpage/core.d.ts +1 -0
  79. package/dist/demo/overlay/inpage/core.js +345 -0
  80. package/dist/demo/overlay/inpage/device-chip.d.ts +1 -0
  81. package/dist/demo/overlay/inpage/device-chip.js +191 -0
  82. package/dist/demo/overlay/inpage/network.d.ts +9 -0
  83. package/dist/demo/overlay/inpage/network.js +200 -0
  84. package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -0
  85. package/dist/demo/overlay/inpage/panel-chrome.js +203 -0
  86. package/dist/demo/overlay/inpage/stamp.d.ts +1 -0
  87. package/dist/demo/overlay/inpage/stamp.js +46 -0
  88. package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -0
  89. package/dist/demo/overlay/inpage/swipe-zoom.js +220 -0
  90. package/dist/demo/overlay/inpage/todos.d.ts +1 -0
  91. package/dist/demo/overlay/inpage/todos.js +294 -0
  92. package/dist/demo/overlay/locator-theater.d.ts +25 -0
  93. package/dist/demo/overlay/locator-theater.js +76 -0
  94. package/dist/demo/overlay/network-capture.d.ts +22 -0
  95. package/dist/demo/overlay/network-capture.js +127 -0
  96. package/dist/demo/overlay/overlay-css.d.ts +3 -0
  97. package/dist/demo/overlay/overlay-css.js +369 -0
  98. package/dist/demo/overlay/overlay-stage.d.ts +23 -0
  99. package/dist/demo/overlay/overlay-stage.js +106 -0
  100. package/dist/demo/overlay/overlay.d.ts +10 -0
  101. package/dist/demo/overlay/overlay.js +89 -0
  102. package/dist/{pilot-overlay/overlay-fixtures.d.ts → demo/overlay/phase-fixtures.d.ts} +2 -2
  103. package/dist/{pilot-overlay/overlay-fixtures.js → demo/overlay/phase-fixtures.js} +2 -2
  104. package/dist/{pilot-overlay/action-ring.js → demo/overlay/pilot/actions.js} +2 -1
  105. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.d.ts +6 -5
  106. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.js +19 -18
  107. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.d.ts +2 -2
  108. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.js +13 -22
  109. package/dist/demo/overlay/reattach.d.ts +7 -0
  110. package/dist/demo/overlay/reattach.js +23 -0
  111. package/dist/demo/overlay/rings.d.ts +33 -0
  112. package/dist/demo/overlay/rings.js +448 -0
  113. package/dist/{ui → demo/overlay/ui}/components/ring.js +2 -2
  114. package/dist/{ui → demo/overlay/ui}/overlay.css +4 -4
  115. package/dist/{ui → demo/overlay/ui}/shadow.d.ts +1 -1
  116. package/dist/{ui → demo/overlay/ui}/shadow.js +39 -2
  117. package/dist/demo/stepper/after.d.ts +3 -0
  118. package/dist/demo/stepper/after.js +113 -0
  119. package/dist/demo/stepper/banner-log.d.ts +37 -0
  120. package/dist/demo/stepper/banner-log.js +63 -0
  121. package/dist/demo/stepper/before.d.ts +4 -0
  122. package/dist/demo/stepper/before.js +110 -0
  123. package/dist/demo/stepper/demo-log.d.ts +31 -0
  124. package/dist/demo/stepper/demo-log.js +309 -0
  125. package/dist/demo/stepper/gate.d.ts +11 -0
  126. package/dist/demo/stepper/gate.js +78 -0
  127. package/dist/demo/stepper/interaction-patch.d.ts +3 -0
  128. package/dist/demo/stepper/interaction-patch.js +323 -0
  129. package/dist/demo/stepper/pacing.d.ts +21 -0
  130. package/dist/demo/stepper/pacing.js +23 -0
  131. package/dist/demo/stepper/slides.d.ts +11 -0
  132. package/dist/demo/stepper/slides.js +233 -0
  133. package/dist/demo/stepper/step-panels.d.ts +21 -0
  134. package/dist/demo/stepper/step-panels.js +589 -0
  135. package/dist/demo/stepper/stepper.d.ts +24 -0
  136. package/dist/demo/stepper/stepper.js +122 -0
  137. package/dist/demo/stepper/teardown.d.ts +48 -0
  138. package/dist/demo/stepper/teardown.js +179 -0
  139. package/dist/demo/stepper/todo-advance.d.ts +14 -0
  140. package/dist/demo/stepper/todo-advance.js +110 -0
  141. package/dist/demo/stepper/view.d.ts +68 -0
  142. package/dist/demo/stepper/view.js +31 -0
  143. package/dist/demo/types.d.ts +17 -0
  144. package/dist/demo/verbose-log.js +15 -0
  145. package/dist/{types.d.ts → engine/block/block.d.ts} +106 -91
  146. package/dist/{core → engine/block}/block.js +10 -53
  147. package/dist/{core → engine/block}/compose.d.ts +10 -7
  148. package/dist/{core → engine/block}/compose.js +1 -1
  149. package/dist/{core/blocks → engine/block/kinds}/api.d.ts +17 -12
  150. package/dist/{core/blocks → engine/block/kinds}/api.js +26 -18
  151. package/dist/{core/blocks → engine/block/kinds}/effect.d.ts +13 -18
  152. package/dist/engine/block/kinds/effect.js +17 -0
  153. package/dist/{core/blocks → engine/block/kinds}/method.d.ts +19 -29
  154. package/dist/{core/blocks → engine/block/kinds}/method.js +7 -21
  155. package/dist/{core/blocks → engine/block/kinds}/nav.d.ts +22 -31
  156. package/dist/{core/blocks → engine/block/kinds}/nav.js +6 -12
  157. package/dist/{core/blocks → engine/block/kinds}/page.d.ts +15 -20
  158. package/dist/{core/blocks → engine/block/kinds}/page.js +5 -7
  159. package/dist/engine/checkpoint/checkpoint.d.ts +22 -0
  160. package/dist/engine/checkpoint/checkpoint.js +8 -0
  161. package/dist/engine/checkpoint/route.d.ts +28 -0
  162. package/dist/engine/checkpoint/route.js +28 -0
  163. package/dist/{core → engine}/config.d.ts +7 -2
  164. package/dist/engine/config.js +6 -0
  165. package/dist/engine/engine.d.ts +45 -0
  166. package/dist/{core → engine}/engine.js +6 -10
  167. package/dist/engine/env.d.ts +59 -0
  168. package/dist/engine/env.js +83 -0
  169. package/dist/{errors.d.ts → engine/errors.d.ts} +23 -22
  170. package/dist/{errors.js → engine/errors.js} +22 -22
  171. package/dist/{core → engine/flow}/branch-regression.d.ts +8 -7
  172. package/dist/{core → engine/flow}/branch-regression.js +4 -3
  173. package/dist/engine/flow/flow.d.ts +162 -0
  174. package/dist/engine/flow/flow.js +244 -0
  175. package/dist/{core → engine/flow}/map-builder.d.ts +42 -40
  176. package/dist/{core → engine/flow}/map-builder.js +46 -48
  177. package/dist/{core → engine}/locate.d.ts +1 -1
  178. package/dist/{core → engine}/locate.js +1 -2
  179. package/dist/{mem-stub.d.ts → engine/mem/mem-stub.d.ts} +9 -8
  180. package/dist/{mem-stub.js → engine/mem/mem-stub.js} +2 -2
  181. package/dist/{mem-page.d.ts → engine/mem/mem.d.ts} +1 -1
  182. package/dist/{mem-page.js → engine/mem/mem.js} +2 -1
  183. package/dist/engine/page-gone.d.ts +5 -0
  184. package/dist/engine/page-gone.js +20 -0
  185. package/dist/engine/run/connect.d.ts +28 -0
  186. package/dist/{types.js → engine/run/connect.js} +11 -10
  187. package/dist/engine/run/events.d.ts +67 -0
  188. package/dist/engine/run/events.js +90 -0
  189. package/dist/engine/run/hooks.d.ts +16 -0
  190. package/dist/engine/run/hooks.js +8 -0
  191. package/dist/engine/run/launch.d.ts +13 -0
  192. package/dist/engine/run/launch.js +27 -0
  193. package/dist/{core/run-graph.d.ts → engine/run/run.d.ts} +9 -11
  194. package/dist/{core/run-graph.js → engine/run/run.js} +22 -11
  195. package/dist/engine/stub/pace.d.ts +12 -0
  196. package/dist/engine/stub/pace.js +2 -0
  197. package/dist/engine/stub/ring.d.ts +130 -0
  198. package/dist/engine/stub/ring.js +41 -0
  199. package/dist/engine/stub/stub.d.ts +268 -0
  200. package/dist/engine/stub/stub.js +1 -0
  201. package/dist/engine/stub/todos.d.ts +104 -0
  202. package/dist/engine/stub/todos.js +2 -0
  203. package/dist/engine/stub/viewport.d.ts +26 -0
  204. package/dist/engine/stub/viewport.js +2 -0
  205. package/dist/{trait.d.ts → engine/trait/trait.d.ts} +1 -1
  206. package/dist/index.d.ts +84 -36
  207. package/dist/index.js +44 -19
  208. package/dist/{session/auto-explore-run.d.ts → live/auto/auto.d.ts} +10 -16
  209. package/dist/{session/auto-explore-run.js → live/auto/auto.js} +164 -248
  210. package/dist/{session/auto-explore.d.ts → live/auto/explore.d.ts} +4 -14
  211. package/dist/{session/auto-explore.js → live/auto/explore.js} +21 -127
  212. package/dist/{auto-session/session.d.ts → live/auto-session/auto-session.d.ts} +1 -1
  213. package/dist/{auto-session/session.js → live/auto-session/auto-session.js} +27 -24
  214. package/dist/{auto-session → live/auto-session}/helpers.d.ts +16 -5
  215. package/dist/{auto-session → live/auto-session}/helpers.js +1 -1
  216. package/dist/{session/auto-session-ipc.d.ts → live/auto-session/ipc.d.ts} +7 -5
  217. package/dist/{session/auto-session-ipc.js → live/auto-session/ipc.js} +31 -16
  218. package/dist/{session/browser.d.ts → live/auto-session/start.d.ts} +1 -2
  219. package/dist/{session/browser.js → live/auto-session/start.js} +2 -3
  220. package/dist/{pilot-overlay → live/pilot}/panel.d.ts +1 -1
  221. package/dist/{pilot-overlay → live/pilot}/panel.js +23 -31
  222. package/dist/{session → live/pilot}/pilot.d.ts +4 -3
  223. package/dist/{session → live/pilot}/pilot.js +4 -4
  224. package/dist/{traverse → live/traverse}/coverage.d.ts +4 -0
  225. package/dist/{traverse → live/traverse}/coverage.js +3 -0
  226. package/dist/{traverse → live/traverse}/lease.d.ts +1 -0
  227. package/dist/{traverse → live/traverse}/lease.js +1 -0
  228. package/dist/{traverse/run.d.ts → live/traverse/traverse.d.ts} +4 -1
  229. package/dist/{traverse/run.js → live/traverse/traverse.js} +26 -43
  230. package/dist/manifest/manifest.d.ts +52 -0
  231. package/dist/manifest/manifest.js +93 -0
  232. package/dist/manifest/map-imports.d.ts +7 -0
  233. package/dist/manifest/map-imports.js +22 -0
  234. package/dist/manifest/maps.d.ts +33 -0
  235. package/dist/manifest/maps.js +62 -0
  236. package/dist/manifest/pack.d.ts +21 -0
  237. package/dist/manifest/pack.js +109 -0
  238. package/dist/manifest/project.d.ts +60 -0
  239. package/dist/manifest/project.js +101 -0
  240. package/dist/{session/block-inject.js → manifest/roots.js} +1 -18
  241. package/dist/manifest/scan.d.ts +19 -0
  242. package/dist/manifest/scan.js +57 -0
  243. package/dist/{blocks-select.d.ts → manifest/select.d.ts} +3 -0
  244. package/dist/{blocks-select.js → manifest/select.js} +2 -0
  245. package/dist/manifest/source.d.ts +23 -0
  246. package/dist/manifest/source.js +86 -0
  247. package/dist/runner/mode.d.ts +71 -0
  248. package/dist/runner/mode.js +1 -0
  249. package/dist/runner/modes/branches.d.ts +5 -0
  250. package/dist/runner/modes/branches.js +37 -0
  251. package/dist/runner/modes/demo.d.ts +3 -0
  252. package/dist/runner/modes/demo.js +13 -0
  253. package/dist/runner/modes/report.d.ts +2 -0
  254. package/dist/runner/modes/report.js +54 -0
  255. package/dist/runner/modes/run.d.ts +2 -0
  256. package/dist/runner/modes/run.js +3 -0
  257. package/dist/runner/options.d.ts +31 -0
  258. package/dist/runner/options.js +42 -0
  259. package/dist/runner/plan/find.d.ts +18 -0
  260. package/dist/runner/plan/find.js +65 -0
  261. package/dist/runner/plan/plan.d.ts +11 -0
  262. package/dist/runner/plan/plan.js +97 -0
  263. package/dist/runner/plan/seed-mem.d.ts +12 -0
  264. package/dist/runner/plan/seed-mem.js +98 -0
  265. package/dist/runner/plan/spec.d.ts +5 -0
  266. package/dist/runner/plan/spec.js +17 -0
  267. package/dist/runner/play-steps.d.ts +2 -0
  268. package/dist/runner/play-steps.js +59 -0
  269. package/dist/runner/runner.d.ts +4 -0
  270. package/dist/runner/runner.js +64 -0
  271. package/dist/runner/session.d.ts +9 -0
  272. package/dist/runner/session.js +87 -0
  273. package/dist/{browser.js → runtime/browser.js} +4 -2
  274. package/dist/{env-file.js → runtime/env-file.js} +7 -12
  275. package/dist/{extensions.d.ts → runtime/extensions.d.ts} +2 -5
  276. package/dist/{extensions.js → runtime/extensions.js} +3 -1
  277. package/dist/runtime/full-launch.d.ts +1 -0
  278. package/dist/runtime/full-launch.js +34 -0
  279. package/dist/runtime/global-flag.d.ts +5 -0
  280. package/dist/runtime/global-flag.js +18 -0
  281. package/dist/{playwright-config.d.ts → runtime/playwright-config.d.ts} +1 -1
  282. package/dist/{playwright.config.js → runtime/playwright.config.js} +3 -2
  283. package/dist/runtime/run-log.d.ts +2 -0
  284. package/dist/runtime/run-log.js +17 -0
  285. package/dist/{video-dir.js → runtime/video-dir.js} +3 -2
  286. package/dist/{config.d.ts → runtime/waygraph-config.d.ts} +8 -9
  287. package/dist/{config.js → runtime/waygraph-config.js} +21 -51
  288. package/dist/{webserver.js → runtime/webserver.js} +5 -30
  289. package/examples/routed-demo/config/waygraph.config.ts +20 -0
  290. package/examples/routed-demo/package.json +1 -4
  291. package/examples/routed-demo/scripts/fixture-server.mjs +1 -1
  292. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +2 -4
  293. package/examples/routed-demo/src/flows/routed-demo.flow.ts +2 -3
  294. package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +5 -4
  295. package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +3 -3
  296. package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +3 -3
  297. package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +3 -3
  298. package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +3 -3
  299. package/examples/routed-demo/src/states/routed-demo.states.ts +5 -3
  300. package/examples/routed-demo/tests/routed-demo.spec.ts +4 -4
  301. package/examples/routed-demo/tsconfig.json +1 -1
  302. package/examples/saucedemo/README.md +11 -12
  303. package/examples/saucedemo/config/waygraph.config.ts +17 -0
  304. package/examples/saucedemo/docs/CONVENTION.md +5 -7
  305. package/examples/saucedemo/docs/HELPERS.md +12 -12
  306. package/examples/saucedemo/package-lock.json +10 -3
  307. package/examples/saucedemo/package.json +12 -29
  308. package/examples/saucedemo/src/blocks/SITE-MAP.md +0 -1
  309. package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +1 -5
  310. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -52
  311. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  312. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  313. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  314. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  315. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  316. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +21 -27
  317. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -9
  318. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  319. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +10 -76
  320. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  321. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  322. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  323. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  324. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  325. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  326. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -29
  327. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -48
  328. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -77
  329. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  330. package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  331. package/examples/saucedemo/src/flows/api-demo.flow.ts +26 -18
  332. package/examples/saucedemo/src/flows/cart-bulk.flow.ts +19 -14
  333. package/examples/saucedemo/src/flows/cart-continue.flow.ts +10 -8
  334. package/examples/saucedemo/src/flows/cart-mem.flow.ts +7 -7
  335. package/examples/saucedemo/src/flows/catalog-logout.flow.ts +13 -8
  336. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +26 -48
  337. package/examples/saucedemo/src/flows/checkout.flow.ts +70 -86
  338. package/examples/saucedemo/src/flows/device-showcase.flow.ts +24 -25
  339. package/examples/saucedemo/src/flows/login.flow.ts +11 -18
  340. package/examples/saucedemo/src/flows/mem-stub-demo.flow.ts +9 -20
  341. package/examples/saucedemo/src/flows/shop.flow.ts +15 -20
  342. package/examples/saucedemo/src/flows/smoke.flow.ts +12 -27
  343. package/examples/saucedemo/src/flows/stub-on-error.flow.ts +24 -43
  344. package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +26 -34
  345. package/examples/saucedemo/src/states/checkout.mem-stubs.ts +11 -0
  346. package/examples/saucedemo/src/states/checkout.states.ts +21 -11
  347. package/examples/saucedemo/src/stubs/device-showcase.ts +191 -0
  348. package/examples/saucedemo/src/stubs/login.ts +37 -0
  349. package/examples/saucedemo/tests/auto-graph.spec.ts +4 -12
  350. package/examples/saucedemo/tests/chain-flow-episodes.spec.ts +7 -9
  351. package/examples/saucedemo/tests/submit-login-branch.spec.ts +18 -5
  352. package/package.json +12 -7
  353. package/templates/agents/waygraph-planner.agent.md +2 -2
  354. package/templates/quickstart/README.md +4 -7
  355. package/templates/quickstart/config/waygraph.config.ts +17 -0
  356. package/templates/quickstart/docs/CONVENTION.md +5 -6
  357. package/templates/quickstart/docs/HELPERS.md +11 -9
  358. package/templates/quickstart/package.json +14 -17
  359. package/templates/quickstart/src/blocks/SITE-MAP.md +13 -3
  360. package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +1 -5
  361. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -52
  362. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  363. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  364. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  365. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  366. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  367. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +21 -27
  368. package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -9
  369. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  370. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +10 -76
  371. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  372. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  373. package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  374. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  375. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  376. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  377. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -29
  378. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -48
  379. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -77
  380. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  381. package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  382. package/templates/quickstart/src/flows/api-demo.flow.ts +45 -0
  383. package/templates/quickstart/src/flows/cart-bulk.flow.ts +19 -14
  384. package/templates/quickstart/src/flows/cart-continue.flow.ts +10 -8
  385. package/templates/quickstart/src/flows/cart-mem.flow.ts +7 -7
  386. package/templates/quickstart/src/flows/catalog-logout.flow.ts +13 -8
  387. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +26 -48
  388. package/templates/quickstart/src/flows/checkout.flow.ts +70 -63
  389. package/templates/quickstart/src/flows/device-showcase.flow.ts +24 -25
  390. package/templates/quickstart/src/flows/login.flow.ts +11 -18
  391. package/templates/quickstart/src/flows/mem-stub-demo.flow.ts +12 -0
  392. package/templates/quickstart/src/flows/shop.flow.ts +15 -20
  393. package/templates/quickstart/src/flows/smoke.flow.ts +12 -27
  394. package/templates/quickstart/src/flows/stub-on-error.flow.ts +31 -0
  395. package/templates/quickstart/src/flows/viewer-blocked.flow.ts +26 -34
  396. package/templates/quickstart/src/states/checkout.mem-stubs.ts +11 -0
  397. package/templates/quickstart/src/states/checkout.states.ts +21 -11
  398. package/templates/quickstart/src/stubs/device-showcase.ts +191 -0
  399. package/templates/quickstart/src/stubs/login.ts +37 -0
  400. package/templates/quickstart/tests/chain-flow.spec.ts +7 -10
  401. package/templates/scaffold/README.md +2 -1
  402. package/templates/scaffold/STRUCTURE.md +5 -4
  403. package/templates/scaffold/config/waygraph.config.ts +1 -0
  404. package/templates/scaffold/gitignore +1 -0
  405. package/templates/scaffold/src/flows/README.md +2 -2
  406. package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +3 -3
  407. package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +3 -3
  408. package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -4
  409. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +3 -3
  410. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +3 -3
  411. package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +5 -4
  412. package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -4
  413. package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -3
  414. package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +3 -3
  415. package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +4 -4
  416. package/templates/scaffold/src/map/(external)/hoppscotch/_keys.ts +21 -0
  417. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +4 -4
  418. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +4 -4
  419. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +4 -4
  420. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +5 -4
  421. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +6 -5
  422. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +6 -5
  423. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +5 -4
  424. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +6 -5
  425. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +6 -5
  426. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +6 -5
  427. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +6 -5
  428. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +6 -5
  429. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +6 -5
  430. package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +3 -3
  431. package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +3 -3
  432. package/templates/scaffold/src/map/(external)/hoppscotch/_states.ts +6 -0
  433. package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +3 -3
  434. package/templates/scaffold/src/map/(external)/mailpit/_keys.ts +13 -0
  435. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +4 -4
  436. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +4 -4
  437. package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +6 -5
  438. package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +6 -5
  439. package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +3 -3
  440. package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +3 -3
  441. package/templates/scaffold/src/map/(external)/mailpit/_states.ts +9 -0
  442. package/templates/scaffold/src/map/README.md +7 -0
  443. package/templates/scaffold/src/states/README.md +4 -1
  444. package/templates/scaffold/src/states/demo.mem-keys.ts +1 -29
  445. package/templates/scaffold/src/states/demo.states.ts +14 -20
  446. package/templates/scaffold/tests/hoppscotch.spec.ts +1 -11
  447. package/templates/scaffold/tests/mail-verify.spec.ts +2 -2
  448. package/templates/skills/waygraph-blind-pilot.skill.md +2 -6
  449. package/templates/skills/waygraph-convention.skill.md +23 -14
  450. package/templates/skills/waygraph-pilot.skill.md +7 -4
  451. package/dist/auto-session/verbose-log.js +0 -16
  452. package/dist/auto-session.d.ts +0 -2
  453. package/dist/auto-session.js +0 -3
  454. package/dist/cli/discover.d.ts +0 -40
  455. package/dist/cli/discover.js +0 -148
  456. package/dist/commands/agent-dive.js +0 -52
  457. package/dist/commands/check.js +0 -192
  458. package/dist/commands/map.js +0 -29
  459. package/dist/commands/run.js +0 -104
  460. package/dist/commands/traverse.js +0 -177
  461. package/dist/core/block.d.ts +0 -109
  462. package/dist/core/blocks/effect.js +0 -23
  463. package/dist/core/config.js +0 -17
  464. package/dist/core/engine.d.ts +0 -198
  465. package/dist/core/flow.d.ts +0 -293
  466. package/dist/core/flow.js +0 -432
  467. package/dist/core.d.ts +0 -14
  468. package/dist/core.js +0 -15
  469. package/dist/highlights/merge.d.ts +0 -8
  470. package/dist/highlights/merge.js +0 -173
  471. package/dist/highlights/stub-ctx.d.ts +0 -10
  472. package/dist/highlights/stub-ctx.js +0 -331
  473. package/dist/highlights/types.d.ts +0 -607
  474. package/dist/highlights.d.ts +0 -9
  475. package/dist/highlights.js +0 -10
  476. package/dist/pilot-overlay.d.ts +0 -5
  477. package/dist/pilot-overlay.js +0 -6
  478. package/dist/runner/banner-log.js +0 -63
  479. package/dist/runner/chain-run.js +0 -102
  480. package/dist/runner/cursor.js +0 -140
  481. package/dist/runner/demo-log.js +0 -316
  482. package/dist/runner/device-stage.d.ts +0 -9
  483. package/dist/runner/device-stage.js +0 -420
  484. package/dist/runner/discovery.js +0 -105
  485. package/dist/runner/index.js +0 -2
  486. package/dist/runner/inpage/banner.d.ts +0 -21
  487. package/dist/runner/inpage/banner.js +0 -156
  488. package/dist/runner/inpage/caption.d.ts +0 -3
  489. package/dist/runner/inpage/caption.js +0 -23
  490. package/dist/runner/inpage/core.d.ts +0 -4
  491. package/dist/runner/inpage/core.js +0 -316
  492. package/dist/runner/inpage/device.d.ts +0 -3
  493. package/dist/runner/inpage/device.js +0 -211
  494. package/dist/runner/inpage/network.d.ts +0 -15
  495. package/dist/runner/inpage/network.js +0 -217
  496. package/dist/runner/inpage/panel-chrome.js +0 -192
  497. package/dist/runner/inpage/stamp.js +0 -46
  498. package/dist/runner/inpage/swipe-zoom.js +0 -220
  499. package/dist/runner/inpage/todos.js +0 -337
  500. package/dist/runner/interaction-patch.js +0 -384
  501. package/dist/runner/main.js +0 -469
  502. package/dist/runner/network-capture.d.ts +0 -9
  503. package/dist/runner/network-capture.js +0 -126
  504. package/dist/runner/overlay-css.d.ts +0 -3
  505. package/dist/runner/overlay-css.js +0 -377
  506. package/dist/runner/overlay-install.js +0 -90
  507. package/dist/runner/overlay-stage.js +0 -110
  508. package/dist/runner/rings.js +0 -514
  509. package/dist/runner/seed-mem.js +0 -110
  510. package/dist/runner/slides.js +0 -278
  511. package/dist/runner/step-mode.js +0 -703
  512. package/dist/runner/step-panels.js +0 -729
  513. package/dist/runner/teardown.js +0 -202
  514. package/dist/runner/todo-dock.js +0 -142
  515. package/dist/session/step-overlay.d.ts +0 -37
  516. package/dist/session/step-overlay.js +0 -244
  517. package/examples/routed-demo/playwright.config.ts +0 -21
  518. package/examples/saucedemo/playwright.config.ts +0 -19
  519. package/examples/saucedemo/scripts/drive-auto-cli.mjs +0 -93
  520. package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +0 -126
  521. package/examples/saucedemo/scripts/prove-auto-graph.mjs +0 -92
  522. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +0 -63
  523. package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  524. package/templates/quickstart/playwright.config.ts +0 -14
  525. package/templates/quickstart/scripts/drive-auto-cli.mjs +0 -93
  526. package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  527. /package/dist/{commands → cli/commands}/agent-dive-scaffold.d.ts +0 -0
  528. /package/dist/{commands → cli/commands}/agent-dive.d.ts +0 -0
  529. /package/dist/{commands → cli/commands}/extensions.d.ts +0 -0
  530. /package/dist/{commands → cli/commands}/init.d.ts +0 -0
  531. /package/dist/{commands → cli/commands}/list.d.ts +0 -0
  532. /package/dist/{commands → cli/commands}/map.d.ts +0 -0
  533. /package/dist/{commands → cli/commands}/session.d.ts +0 -0
  534. /package/dist/{commands → cli/commands}/test.d.ts +0 -0
  535. /package/dist/{commands → cli/commands}/traverse.d.ts +0 -0
  536. /package/dist/{commands → cli/commands}/try.d.ts +0 -0
  537. /package/dist/{commands → cli/commands}/upgrade.d.ts +0 -0
  538. /package/dist/{highlights → demo/narration}/shorthand.js +0 -0
  539. /package/dist/{pilot-overlay/action-ring.d.ts → demo/overlay/pilot/actions.d.ts} +0 -0
  540. /package/dist/{ui → demo/overlay/ui}/components/ring.d.ts +0 -0
  541. /package/dist/{ui → demo/overlay/ui}/stylesheet.d.ts +0 -0
  542. /package/dist/{ui → demo/overlay/ui}/stylesheet.js +0 -0
  543. /package/dist/{ui → demo/overlay/ui}/tokens.d.ts +0 -0
  544. /package/dist/{ui → demo/overlay/ui}/tokens.js +0 -0
  545. /package/dist/{highlights → demo}/types.js +0 -0
  546. /package/dist/{auto-session → demo}/verbose-log.d.ts +0 -0
  547. /package/dist/{selector.d.ts → engine/trait/selector.d.ts} +0 -0
  548. /package/dist/{selector.js → engine/trait/selector.js} +0 -0
  549. /package/dist/{trait.js → engine/trait/trait.js} +0 -0
  550. /package/dist/{session/block-inject.d.ts → manifest/roots.d.ts} +0 -0
  551. /package/dist/{browser.d.ts → runtime/browser.d.ts} +0 -0
  552. /package/dist/{env-file.d.ts → runtime/env-file.d.ts} +0 -0
  553. /package/dist/{playwright-config.js → runtime/playwright-config.js} +0 -0
  554. /package/dist/{playwright.config.d.ts → runtime/playwright.config.d.ts} +0 -0
  555. /package/dist/{video-dir.d.ts → runtime/video-dir.d.ts} +0 -0
  556. /package/dist/{webserver.d.ts → runtime/webserver.d.ts} +0 -0
@@ -0,0 +1,87 @@
1
+ // The browser a run plays in: launched with the project's extensions, sized for the mode and an optional video.
2
+ import { mkdirSync } from "node:fs";
3
+ import { recordArtifact } from "../engine/run/events.js";
4
+ import { chromiumExecutablePath, extensionPathsFromEnv, launchContext } from "../runtime/browser.js";
5
+ import { resolveVideoDir } from "../runtime/video-dir.js";
6
+ import { ignorePageGone } from "../engine/page-gone.js";
7
+ /** WAYGRAPH_VIDEO_VIEWPORT / --video-viewport: "1920x1080" or "1920,1080". */
8
+ function parseVideoViewport(raw) {
9
+ const m = raw?.trim().match(/^(\d{3,5})[xX,](\d{3,5})$/);
10
+ if (!m)
11
+ return null;
12
+ const width = Number(m[1]);
13
+ const height = Number(m[2]);
14
+ if (width < 320 || height < 240 || width > 7680 || height > 4320)
15
+ return null;
16
+ return { width, height };
17
+ }
18
+ /**
19
+ * A demo window fills the screen (viewport null, maximized). A video is a fixed 16:9 capture (1920x1080 for a demo,
20
+ * 1280x720 for a run) with the device scale locked, so the recording keeps that size on HiDPI hosts.
21
+ */
22
+ function viewportFor(options, videoSize) {
23
+ if (videoSize)
24
+ return { viewport: videoSize, deviceScaleFactor: 1 };
25
+ return options.mode === "demo" ? { viewport: null } : { viewport: { width: 1280, height: 720 } };
26
+ }
27
+ export async function openSession(projectDir, options, mem, launchSlowMo) {
28
+ const videoDir = options.video ? (options.video === "1" ? await resolveVideoDir(projectDir) : options.video) : null;
29
+ if (videoDir)
30
+ mkdirSync(videoDir, { recursive: true });
31
+ const videoSize = videoDir
32
+ ? (parseVideoViewport(options.videoViewport) ?? (options.mode === "demo" ? { width: 1920, height: 1080 } : { width: 1280, height: 720 }))
33
+ : null;
34
+ const { chromium } = await import("@playwright/test");
35
+ const executablePath = chromiumExecutablePath();
36
+ const { context, close: closeBrowser } = await launchContext({
37
+ launcher: chromium,
38
+ launch: {
39
+ headless: !options.headed,
40
+ ...(launchSlowMo !== undefined ? { slowMo: launchSlowMo } : {}),
41
+ args: options.mode === "demo" || videoSize ? ["--start-maximized"] : [],
42
+ ...(executablePath ? { executablePath } : {}),
43
+ },
44
+ context: {
45
+ ...(options.baseURL ? { baseURL: options.baseURL } : {}),
46
+ hasTouch: true,
47
+ ...viewportFor(options, videoSize),
48
+ ...(videoDir ? { recordVideo: videoSize ? { dir: videoDir, size: videoSize } : { dir: videoDir } } : {}),
49
+ },
50
+ extensions: extensionPathsFromEnv(),
51
+ });
52
+ const page = (await context.newPage());
53
+ if (videoSize)
54
+ page.__wgVideoViewport = videoSize;
55
+ // The first step's panel shows over the real app, not a blank page.
56
+ if (options.baseURL)
57
+ await page.goto(options.baseURL).catch(ignorePageGone);
58
+ const close = async () => {
59
+ // A recording's last moment (a ring, the network panel) would be cut off mid-fade without a little room.
60
+ if (videoDir && !page.isClosed())
61
+ await new Promise((r) => setTimeout(r, 1800));
62
+ await context.close();
63
+ const video = await page.video()?.path().catch(() => null);
64
+ if (video) {
65
+ console.log("waygraph: video saved to " + video);
66
+ recordArtifact("video", video);
67
+ }
68
+ await closeBrowser();
69
+ };
70
+ return { session: { context, page, mem, baseURL: options.baseURL }, close };
71
+ }
72
+ /** A fresh session between episodes: no cookies, no storage, back on the base URL (so the page itself looks fresh too). */
73
+ export async function resetPage(session) {
74
+ await session.context.clearCookies().catch(ignorePageGone);
75
+ await session.page
76
+ .evaluate(() => {
77
+ try {
78
+ localStorage.clear();
79
+ sessionStorage.clear();
80
+ }
81
+ catch {
82
+ /* storage blocked (e.g. about:blank) - nothing to clear anyway */
83
+ }
84
+ })
85
+ .catch(ignorePageGone);
86
+ await session.page.goto(session.baseURL || "about:blank").catch(ignorePageGone);
87
+ }
@@ -1,6 +1,8 @@
1
1
  import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
+ import { envString } from "../engine/env.js";
5
+ import { ignoreTimeout } from "../engine/page-gone.js";
4
6
  let warned = false;
5
7
  /**
6
8
  * CHROME_PATH / CHROMIUM_PATH, if set and the file exists. A stale path (browser uninstalled)
@@ -20,7 +22,7 @@ export function chromiumExecutablePath() {
20
22
  }
21
23
  /** Unpacked extension directories, as resolved by `resolveExtensions` - also what `WAYGRAPH_EXTENSIONS` carries to child processes. */
22
24
  export function extensionPathsFromEnv() {
23
- return (process.env.WAYGRAPH_EXTENSIONS ?? "").split(",").filter(Boolean);
25
+ return (envString("WAYGRAPH_EXTENSIONS") ?? "").split(",").filter(Boolean);
24
26
  }
25
27
  /**
26
28
  * Launches a browser and its first context. With `extensions` it uses a persistent context, the only
@@ -49,7 +51,7 @@ export async function launchContext(opts) {
49
51
  // An extension's background worker registers its page hooks, so wait for it before the first navigation.
50
52
  const hasWorker = extensions.some((dir) => JSON.parse(readFileSync(join(dir, "manifest.json"), "utf-8")).background?.service_worker !== undefined);
51
53
  if (hasWorker && context.serviceWorkers().length === 0) {
52
- await context.waitForEvent("serviceworker", { timeout: 10_000 }).catch(() => undefined);
54
+ await context.waitForEvent("serviceworker", { timeout: 10_000 }).catch(ignoreTimeout);
53
55
  }
54
56
  return {
55
57
  browser: context.browser(),
@@ -5,6 +5,8 @@
5
5
  // field) to get waygraph to see the same config their actual app already uses.
6
6
  import { existsSync, readFileSync } from "node:fs";
7
7
  import { join } from "node:path";
8
+ import { envString, setEnv } from "../engine/env.js";
9
+ import { takeGlobalFlag } from "./global-flag.js";
8
10
  /** `KEY=value` lines only - no `${VAR}` expansion, no multiline values. Matches the common
9
11
  * Vite/Next `.env` shape, not full dotenv-expand parity. */
10
12
  function parseEnvFile(content) {
@@ -30,21 +32,14 @@ function parseEnvFile(content) {
30
32
  }
31
33
  /** The env mode: `--env <mode>` / `WAYGRAPH_ENV`, else `NODE_ENV`, else "development". */
32
34
  export function envMode() {
33
- return process.env.WAYGRAPH_ENV || process.env.NODE_ENV || "development";
35
+ return envString("WAYGRAPH_ENV") || process.env.NODE_ENV || "development";
34
36
  }
35
37
  /** Removes `--env <mode>` / `--env=<mode>` from argv and records it as `WAYGRAPH_ENV`, so it never reaches a forwarded command. */
36
38
  export function takeEnvFlag(argv) {
37
- const out = [];
38
- for (let i = 0; i < argv.length; i++) {
39
- const a = argv[i];
40
- if (a === "--env" && argv[i + 1] !== undefined)
41
- process.env.WAYGRAPH_ENV = argv[++i];
42
- else if (a.startsWith("--env="))
43
- process.env.WAYGRAPH_ENV = a.slice("--env=".length);
44
- else
45
- out.push(a);
46
- }
47
- return out;
39
+ const { value, rest } = takeGlobalFlag(argv, "env");
40
+ if (value !== undefined)
41
+ setEnv("WAYGRAPH_ENV", value);
42
+ return rest;
48
43
  }
49
44
  /**
50
45
  * Loads `.env` / `.env.local` / `.env.<mode>` / `.env.<mode>.local` from a project's root, the layering
@@ -1,9 +1,6 @@
1
1
  /** A known name (`"hoppscotch"`), a Chrome Web Store id, a path to an unpacked extension, or `{ id, sha256 }`. */
2
- export type ExtensionSpec = string | {
3
- id?: string;
4
- path?: string;
5
- sha256?: string;
6
- };
2
+ import type { ExtensionSpec } from "../engine/config.js";
3
+ /** Names accepted in `extensions: [...]` mapped to their Chrome Web Store ids. */
7
4
  export declare const KNOWN_EXTENSIONS: Readonly<Record<string, string>>;
8
5
  /** Unpacks a .crx and pins the manifest `key`, so the extension keeps its store id (its origin is then stable, e.g. for an API allowlist). */
9
6
  export declare function unpackCrx(crx: Buffer, dest: string): void;
@@ -4,12 +4,14 @@ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join, resolve, sep } from "node:path";
6
6
  import { inflateRawSync } from "node:zlib";
7
+ import { envString } from "../engine/env.js";
8
+ /** Names accepted in `extensions: [...]` mapped to their Chrome Web Store ids. */
7
9
  export const KNOWN_EXTENSIONS = {
8
10
  hoppscotch: "amknoiejhlmhancpahfcfcfhllgkpbld",
9
11
  };
10
12
  const STORE_ID = /^[a-p]{32}$/;
11
13
  function cacheDir() {
12
- const base = process.env.WAYGRAPH_CACHE_DIR ?? join(process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "waygraph");
14
+ const base = envString("WAYGRAPH_CACHE_DIR") ?? join(process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "waygraph");
13
15
  return join(base, "extensions");
14
16
  }
15
17
  /** Reads the end-of-central-directory record and extracts every entry; rejects paths that escape `dest`. */
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { setOwnContextLauncher } from "../engine/run/launch.js";
2
+ import { resolveLauncher } from "../engine/config.js";
3
+ import { chromiumExecutablePath, extensionPathsFromEnv, launchContext } from "./browser.js";
4
+ import { resolveExtensions } from "./extensions.js";
5
+ import { loadWaygraphConfig } from "./waygraph-config.js";
6
+ import { envString } from "../engine/env.js";
7
+ // An Engine's own browser follows the selected config (--config), the Chromium override and the configured extensions.
8
+ setOwnContextLauncher(async (engineConfig) => {
9
+ // A config chosen with `--config` / WAYGRAPH_CONFIG wins over the one the Engine was built with.
10
+ const chosen = envString("WAYGRAPH_CONFIG") ? await loadWaygraphConfig(process.cwd()) : undefined;
11
+ const config = chosen
12
+ ? {
13
+ ...engineConfig,
14
+ ...(chosen.baseUrl !== undefined ? { baseUrl: chosen.baseUrl } : {}),
15
+ ...(chosen.extensions !== undefined ? { extensions: chosen.extensions } : {}),
16
+ }
17
+ : engineConfig;
18
+ const browserName = config?.browserName ?? "chromium";
19
+ const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
20
+ const baseURL = config?.baseUrl ?? envString("WAYGRAPH_BASE_URL");
21
+ return launchContext({
22
+ launcher: resolveLauncher(browserName, config),
23
+ launch: {
24
+ headless: config?.headless ?? true,
25
+ ...(config?.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
26
+ ...(executablePath ? { executablePath } : {}),
27
+ },
28
+ context: {
29
+ ...(baseURL ? { baseURL } : {}),
30
+ ...(config?.recordVideo ? { recordVideo: config.recordVideo } : {}),
31
+ },
32
+ extensions: await resolveExtensions(config?.extensions ?? extensionPathsFromEnv(), process.cwd()),
33
+ });
34
+ });
@@ -0,0 +1,5 @@
1
+ /** The value of `--<name> <v>` / `--<name>=<v>` (the last one wins) and argv without it. */
2
+ export declare function takeGlobalFlag(argv: string[], name: string): {
3
+ value: string | undefined;
4
+ rest: string[];
5
+ };
@@ -0,0 +1,18 @@
1
+ // Options any command takes (`--config`, `--env`): read with node:util's parseArgs and taken out of argv, so they never
2
+ // reach a command that forwards its arguments (waygraph test -> playwright test).
3
+ import { parseArgs } from "node:util";
4
+ /** The value of `--<name> <v>` / `--<name>=<v>` (the last one wins) and argv without it. */
5
+ export function takeGlobalFlag(argv, name) {
6
+ const { tokens } = parseArgs({ args: argv, options: { [name]: { type: "string" } }, strict: false, allowPositionals: true, tokens: true });
7
+ let value;
8
+ const drop = new Set();
9
+ for (const t of tokens) {
10
+ if (t.kind !== "option" || t.name !== name || typeof t.value !== "string")
11
+ continue;
12
+ value = t.value;
13
+ drop.add(t.index);
14
+ if (!t.inlineValue)
15
+ drop.add(t.index + 1);
16
+ }
17
+ return { value, rest: argv.filter((_, i) => !drop.has(i)) };
18
+ }
@@ -1,4 +1,4 @@
1
1
  import type { PlaywrightTestConfig } from "@playwright/test";
2
- import type { WaygraphConfig } from "./config.js";
2
+ import type { WaygraphConfig } from "./waygraph-config.js";
3
3
  /** The test runner's config for a project, built from its waygraph config. `waygraph test` uses this when there is no playwright.config. */
4
4
  export declare function playwrightConfigFrom(config: WaygraphConfig, projectDir: string, baseURL: string | undefined): PlaywrightTestConfig;
@@ -1,6 +1,7 @@
1
1
  // Loaded by `waygraph test` (playwright test -c) for projects that keep their settings in config/waygraph.config.ts.
2
2
  import { defineConfig } from "@playwright/test";
3
- import { loadWaygraphConfig, resolveBaseUrl } from "./config.js";
3
+ import { loadWaygraphConfig, resolveBaseUrl } from "./waygraph-config.js";
4
4
  import { playwrightConfigFrom } from "./playwright-config.js";
5
- const projectDir = process.env.WAYGRAPH_PROJECT_DIR ?? process.cwd();
5
+ import { envString } from "../engine/env.js";
6
+ const projectDir = envString("WAYGRAPH_PROJECT_DIR") ?? process.cwd();
6
7
  export default defineConfig(playwrightConfigFrom((await loadWaygraphConfig(projectDir)) ?? {}, projectDir, await resolveBaseUrl(projectDir)));
@@ -0,0 +1,2 @@
1
+ /** The folder run logs go to for a project unless the config or the environment says otherwise. */
2
+ export declare function defaultRunLogDir(projectDir: string): string;
@@ -0,0 +1,17 @@
1
+ // Writes every run event to `<dir>/<runId>.jsonl` when WAYGRAPH_RUN_LOG names a folder (the CLI sets it to the project's
2
+ // `.waygraph/runs`; `runLog: false` in the config turns it off). This is the run history Waygraph UI reads.
3
+ import { appendFileSync, mkdirSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { onRunEvent } from "../engine/run/events.js";
6
+ import { envString } from "../engine/env.js";
7
+ onRunEvent((event) => {
8
+ const dir = envString("WAYGRAPH_RUN_LOG");
9
+ if (!dir || dir === "0")
10
+ return;
11
+ mkdirSync(dir, { recursive: true });
12
+ appendFileSync(join(dir, `${event.runId}.jsonl`), JSON.stringify(event) + "\n");
13
+ });
14
+ /** The folder run logs go to for a project unless the config or the environment says otherwise. */
15
+ export function defaultRunLogDir(projectDir) {
16
+ return join(projectDir, ".waygraph", "runs");
17
+ }
@@ -1,7 +1,8 @@
1
1
  import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { basename, isAbsolute, join, resolve } from "node:path";
4
- import { loadWaygraphConfig } from "./config.js";
4
+ import { loadWaygraphConfig } from "./waygraph-config.js";
5
+ import { envString } from "../engine/env.js";
5
6
  /** The user's Downloads folder, or undefined when there is none (a server, a container). */
6
7
  export function downloadsDir() {
7
8
  const home = homedir();
@@ -41,7 +42,7 @@ function writable(dir) {
41
42
  */
42
43
  export async function resolveVideoDir(projectDir) {
43
44
  const fallback = join(projectDir, ".waygraph-videos");
44
- const configured = process.env.WAYGRAPH_VIDEO_DIR || (await loadWaygraphConfig(projectDir))?.video?.dir;
45
+ const configured = envString("WAYGRAPH_VIDEO_DIR") || (await loadWaygraphConfig(projectDir))?.video?.dir;
45
46
  if (configured) {
46
47
  const dir = isAbsolute(expandHome(configured)) ? expandHome(configured) : resolve(projectDir, configured);
47
48
  if (writable(dir))
@@ -1,7 +1,8 @@
1
1
  import type { PlaywrightTestConfig } from "@playwright/test";
2
- import type { ExtensionSpec } from "./extensions.js";
2
+ import type { ExtensionSpec } from "../engine/config.js";
3
3
  import type { WebServerConfig } from "./webserver.js";
4
- import type { DemoPace } from "./highlights.js";
4
+ import type { DemoPace } from "../engine/stub/pace.js";
5
+ /** Where `--video` recordings are saved and at what size. */
5
6
  export interface VideoSettings {
6
7
  /** Where recordings are saved: absolute, `~/…`, or relative to the project. Default `~/Downloads/waygraph-videos/<project>` (the project's `.waygraph-videos/` where there is no Downloads folder, and on CI). */
7
8
  dir?: string;
@@ -40,6 +41,7 @@ export interface DemoSettings extends RunSettings {
40
41
  /** Shorter Next / auto-next gates; keeps the cursor and typing animation. */
41
42
  fast?: boolean;
42
43
  }
44
+ /** The project config in `config/waygraph.config.ts`: base URL, extensions, run and demo settings, web server and the Playwright block. */
43
45
  export interface WaygraphConfig {
44
46
  /** Same value `resolveBaseUrl` would otherwise read from package.json's `waygraph.baseUrl`. */
45
47
  baseUrl?: string;
@@ -55,6 +57,8 @@ export interface WaygraphConfig {
55
57
  run?: RunSettings;
56
58
  /** Settings for `waygraph demo` only. They override the shared ones above. */
57
59
  demo?: DemoSettings;
60
+ /** Write each run's events to `.waygraph/runs/<runId>.jsonl` (the history Waygraph UI shows), or to this folder. Default true. */
61
+ runLog?: boolean | string;
58
62
  /** Folder of test files, relative to the project. Default `"tests"`. */
59
63
  testDir?: string;
60
64
  /** App to start around `waygraph test`, `run`, `demo` and `auto` (same fields as Playwright's `webServer`). */
@@ -77,7 +81,7 @@ export declare function defineConfig(config: WaygraphConfig | ((context: ConfigC
77
81
  export declare function takeConfigFlag(argv: string[]): string[];
78
82
  /**
79
83
  * Looks for the first `waygraph.config.*` in `projectDir` and imports it - `.ts` works
80
- * unmodified because `bin/waygraph` already registers `tsx/esm` before `dist/cli.js` ever runs
84
+ * unmodified because `bin/waygraph` already registers `tsx/esm` before `dist/cli/cli.js` ever runs
81
85
  * (the same mechanism that already lets a consumer's `.block.ts`/`.flow.ts` import directly), so
82
86
  * no separate loader/transpile step is needed here. A broken config file throws loud, naming the
83
87
  * file - silently swallowing it would make a missing `baseUrl` look like "nobody configured
@@ -86,7 +90,7 @@ export declare function takeConfigFlag(argv: string[]): string[];
86
90
  export declare function loadWaygraphConfig(projectDir: string): Promise<WaygraphConfig | undefined>;
87
91
  /**
88
92
  * Single source of truth for a project's base URL. Was three independently drifted copies
89
- * (`src/cli/flags.ts`, `src/traverse/run.ts`, `src/session/auto-explore-run.ts`), each checking
93
+ * (`src/cli/flags.ts`, `src/live/traverse/traverse.ts`, `src/live/auto/auto.ts`), each checking
90
94
  * a slightly different subset of sources in a different order - real duplication, not just
91
95
  * stylistic, since one copy skipped `config.waygraph.*` nesting and another checked
92
96
  * `WAYGRAPH_BASE_URL` first instead of last. Checked in this order:
@@ -95,11 +99,6 @@ export declare function loadWaygraphConfig(projectDir: string): Promise<Waygraph
95
99
  * `loadEnvFiles`, called here so every caller gets native `.env` support for free, not just
96
100
  * whichever command remembered to call it).
97
101
  * 2. A `waygraph.config.*` file's `baseUrl`.
98
- * 3. `package.json`'s `waygraph.baseUrl`/`baseURL` (`config.waygraph.*` also checked - a common
99
- * nested-config convention some tooling uses).
100
- * 4. `playwright.config.*`'s own `baseURL` (regex-read as text, never imported - importing a
101
- * consumer's real playwright.config risks pulling in `@playwright/test`'s own global setup
102
- * as a side effect, which resolving a URL string has no business doing).
103
102
  */
104
103
  export declare function resolveBaseUrl(projectDir: string): Promise<string | undefined>;
105
104
  /** Unpacked extension directories for a run: `WAYGRAPH_EXTENSIONS` if set, else the config file's `extensions` (fetched on first use). */
@@ -2,12 +2,14 @@
2
2
  // keeps working untouched; this is a second, richer place to put the same kind of project-level
3
3
  // setting, for consumers who'd rather have a real typed file than a JSON field. Real ask: "I
4
4
  // think its time to add waygraph config now."
5
- import { existsSync, readFileSync } from "node:fs";
5
+ import { existsSync } from "node:fs";
6
6
  import { isAbsolute, join } from "node:path";
7
7
  import { pathToFileURL } from "node:url";
8
8
  import { extensionPathsFromEnv } from "./browser.js";
9
9
  import { envMode, loadEnvFiles } from "./env-file.js";
10
10
  import { resolveExtensions } from "./extensions.js";
11
+ import { envString, setEnv } from "../engine/env.js";
12
+ import { takeGlobalFlag } from "./global-flag.js";
11
13
  /**
12
14
  * Typed identity helper, like `defineConfig` in `vite.config.ts`. Pass an object, or a function when values come
13
15
  * from `.env` files (`.env`, `.env.local`, `.env.<mode>`; pick the mode with `--env <mode>`):
@@ -27,7 +29,7 @@ const CONFIG_FILENAMES = [...CONFIG_NAMES.map((n) => join("config", n)), ...CONF
27
29
  * (`staging` -> `config/waygraph.staging.config.ts`, also tried in the project root). Without it, `waygraph.config.*`.
28
30
  */
29
31
  function configCandidates() {
30
- const chosen = process.env.WAYGRAPH_CONFIG;
32
+ const chosen = envString("WAYGRAPH_CONFIG");
31
33
  if (!chosen)
32
34
  return CONFIG_FILENAMES;
33
35
  if (/[\\/]/.test(chosen) || /\.[cm]?[jt]s$/.test(chosen))
@@ -37,21 +39,14 @@ function configCandidates() {
37
39
  }
38
40
  /** Removes `--config <file>` / `--config=<file>` from argv and records it as `WAYGRAPH_CONFIG`, so every command reads that config. */
39
41
  export function takeConfigFlag(argv) {
40
- const out = [];
41
- for (let i = 0; i < argv.length; i++) {
42
- const a = argv[i];
43
- if (a === "--config" && argv[i + 1] !== undefined)
44
- process.env.WAYGRAPH_CONFIG = argv[++i];
45
- else if (a.startsWith("--config="))
46
- process.env.WAYGRAPH_CONFIG = a.slice("--config=".length);
47
- else
48
- out.push(a);
49
- }
50
- return out;
42
+ const { value, rest } = takeGlobalFlag(argv, "config");
43
+ if (value !== undefined)
44
+ setEnv("WAYGRAPH_CONFIG", value);
45
+ return rest;
51
46
  }
52
47
  /**
53
48
  * Looks for the first `waygraph.config.*` in `projectDir` and imports it - `.ts` works
54
- * unmodified because `bin/waygraph` already registers `tsx/esm` before `dist/cli.js` ever runs
49
+ * unmodified because `bin/waygraph` already registers `tsx/esm` before `dist/cli/cli.js` ever runs
55
50
  * (the same mechanism that already lets a consumer's `.block.ts`/`.flow.ts` import directly), so
56
51
  * no separate loader/transpile step is needed here. A broken config file throws loud, naming the
57
52
  * file - silently swallowing it would make a missing `baseUrl` look like "nobody configured
@@ -62,8 +57,8 @@ export async function loadWaygraphConfig(projectDir) {
62
57
  for (const name of configCandidates()) {
63
58
  const p = isAbsolute(name) ? name : join(projectDir, name);
64
59
  if (!existsSync(p)) {
65
- if (process.env.WAYGRAPH_CONFIG && name === process.env.WAYGRAPH_CONFIG) {
66
- throw new Error(`waygraph: config "${process.env.WAYGRAPH_CONFIG}" not found (looked for ${p})`);
60
+ if (envString("WAYGRAPH_CONFIG") && name === envString("WAYGRAPH_CONFIG")) {
61
+ throw new Error(`waygraph: config "${envString("WAYGRAPH_CONFIG")}" not found (looked for ${p})`);
67
62
  }
68
63
  continue;
69
64
  }
@@ -82,7 +77,7 @@ export async function loadWaygraphConfig(projectDir) {
82
77
  }
83
78
  /**
84
79
  * Single source of truth for a project's base URL. Was three independently drifted copies
85
- * (`src/cli/flags.ts`, `src/traverse/run.ts`, `src/session/auto-explore-run.ts`), each checking
80
+ * (`src/cli/flags.ts`, `src/live/traverse/traverse.ts`, `src/live/auto/auto.ts`), each checking
86
81
  * a slightly different subset of sources in a different order - real duplication, not just
87
82
  * stylistic, since one copy skipped `config.waygraph.*` nesting and another checked
88
83
  * `WAYGRAPH_BASE_URL` first instead of last. Checked in this order:
@@ -91,43 +86,14 @@ export async function loadWaygraphConfig(projectDir) {
91
86
  * `loadEnvFiles`, called here so every caller gets native `.env` support for free, not just
92
87
  * whichever command remembered to call it).
93
88
  * 2. A `waygraph.config.*` file's `baseUrl`.
94
- * 3. `package.json`'s `waygraph.baseUrl`/`baseURL` (`config.waygraph.*` also checked - a common
95
- * nested-config convention some tooling uses).
96
- * 4. `playwright.config.*`'s own `baseURL` (regex-read as text, never imported - importing a
97
- * consumer's real playwright.config risks pulling in `@playwright/test`'s own global setup
98
- * as a side effect, which resolving a URL string has no business doing).
99
89
  */
100
90
  export async function resolveBaseUrl(projectDir) {
101
91
  loadEnvFiles(projectDir);
102
- if (process.env.WAYGRAPH_BASE_URL)
103
- return process.env.WAYGRAPH_BASE_URL;
92
+ if (envString("WAYGRAPH_BASE_URL"))
93
+ return envString("WAYGRAPH_BASE_URL");
104
94
  const config = await loadWaygraphConfig(projectDir);
105
95
  if (config?.baseUrl && config.baseUrl.trim())
106
96
  return config.baseUrl.trim();
107
- const pkgPath = join(projectDir, "package.json");
108
- if (existsSync(pkgPath)) {
109
- try {
110
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
111
- const fromPkg = pkg.waygraph?.baseUrl ??
112
- pkg.waygraph?.baseURL ??
113
- pkg.config?.waygraph?.baseUrl ??
114
- pkg.config?.waygraph?.baseURL;
115
- if (typeof fromPkg === "string" && fromPkg.trim())
116
- return fromPkg.trim();
117
- }
118
- catch {
119
- // ignore malformed package.json - fall through to playwright.config
120
- }
121
- }
122
- for (const name of ["playwright.config.ts", "playwright.config.mts", "playwright.config.js", "playwright.config.mjs"]) {
123
- const p = join(projectDir, name);
124
- if (!existsSync(p))
125
- continue;
126
- const src = readFileSync(p, "utf-8");
127
- const m = src.match(/baseURL\s*:\s*["']([^"']+)["']/);
128
- if (m?.[1])
129
- return m[1];
130
- }
131
97
  return undefined;
132
98
  }
133
99
  /** Unpacked extension directories for a run: `WAYGRAPH_EXTENSIONS` if set, else the config file's `extensions` (fetched on first use). */
@@ -143,18 +109,22 @@ export async function configuredExtensions(projectDir) {
143
109
  * (`WAYGRAPH_COMMAND`, set by the CLI). The `run` / `demo` section overrides the shared top-level values. A flag, a shell
144
110
  * variable or a `.env` value that is already set always wins, so the config only supplies defaults.
145
111
  */
146
- export function applyConfigEnv(config, command = process.env.WAYGRAPH_COMMAND) {
112
+ export function applyConfigEnv(config, command = envString("WAYGRAPH_COMMAND")) {
147
113
  if (!config)
148
114
  return;
149
115
  const isDemo = command === "demo" || command === "try";
150
116
  const section = isDemo ? config.demo : command === "run" ? config.run : undefined;
151
117
  const set = (name, value) => {
152
- if (value !== undefined && process.env[name] === undefined)
153
- process.env[name] = value;
118
+ if (value !== undefined && envString(name) === undefined)
119
+ setEnv(name, value);
154
120
  };
155
121
  const flag = (b) => (b === undefined ? undefined : b ? "1" : "0");
156
122
  const video = { ...config.video, ...section?.video };
157
123
  const slowMo = section?.slowMo ?? config.slowMo;
124
+ if (config.runLog === false)
125
+ set("WAYGRAPH_RUN_LOG", "0");
126
+ else if (typeof config.runLog === "string")
127
+ set("WAYGRAPH_RUN_LOG", config.runLog);
158
128
  set("WAYGRAPH_VIDEO_DIR", video.dir);
159
129
  set("WAYGRAPH_VIDEO_VIEWPORT", video.viewport);
160
130
  set("WAYGRAPH_SLOWMO", slowMo === undefined ? undefined : String(slowMo));
@@ -1,38 +1,13 @@
1
- // Starts/stops a project's `webServer` (waygraph.config, or a legacy playwright.config) around `waygraph run`/`demo`/`auto`,
1
+ // Starts/stops a project's `webServer` (from config/waygraph.config.ts) around `waygraph run`/`demo`/`auto`,
2
2
  // the same block `waygraph test` already honors.
3
- import { existsSync } from "node:fs";
4
3
  import { join } from "node:path";
5
- import { pathToFileURL } from "node:url";
6
4
  import { spawn } from "node:child_process";
7
- import { loadWaygraphConfig } from "./config.js";
8
- const CONFIG_FILES = [
9
- "playwright.config.ts",
10
- "playwright.config.mts",
11
- "playwright.config.mjs",
12
- "playwright.config.js",
13
- "playwright.config.cjs",
14
- ];
5
+ import { loadWaygraphConfig } from "./waygraph-config.js";
15
6
  async function loadWebServerConfigs(projectDir) {
16
7
  const fromWaygraph = (await loadWaygraphConfig(projectDir))?.webServer;
17
- if (fromWaygraph)
18
- return Array.isArray(fromWaygraph) ? fromWaygraph : [fromWaygraph];
19
- for (const name of CONFIG_FILES) {
20
- const p = join(projectDir, name);
21
- if (!existsSync(p))
22
- continue;
23
- let mod;
24
- try {
25
- mod = (await import(pathToFileURL(p).href));
26
- }
27
- catch (err) {
28
- throw new Error(`waygraph: failed to load ${name}: ${err instanceof Error ? err.message : String(err)}`);
29
- }
30
- const webServer = mod.default?.webServer;
31
- if (!webServer)
32
- return [];
33
- return Array.isArray(webServer) ? webServer : [webServer];
34
- }
35
- return [];
8
+ if (!fromWaygraph)
9
+ return [];
10
+ return Array.isArray(fromWaygraph) ? fromWaygraph : [fromWaygraph];
36
11
  }
37
12
  async function isUp(target) {
38
13
  try {
@@ -0,0 +1,20 @@
1
+ import { Engine, defineConfig } from "waygraph";
2
+
3
+ const config = defineConfig({
4
+ baseUrl: "http://127.0.0.1:4277",
5
+ testDir: "./tests",
6
+ webServer: {
7
+ command: "node scripts/fixture-server.mjs",
8
+ url: "http://127.0.0.1:4277/dashboard",
9
+ reuseExistingServer: !process.env.CI,
10
+ },
11
+ playwright: {
12
+ workers: 1,
13
+ fullyParallel: false,
14
+ timeout: 30_000,
15
+ use: { headless: true, trace: "retain-on-failure" },
16
+ },
17
+ });
18
+
19
+ export default config;
20
+ export const engine = new Engine(config);
@@ -6,15 +6,12 @@
6
6
  "description": "Waygraph Map folder convention proof - (group)/<page>/page.block.ts + nav.block.ts + methods/*.block.ts, offline fixture, zero new engine code.",
7
7
  "scripts": {
8
8
  "typecheck": "tsc --noEmit",
9
- "test": "playwright test",
9
+ "test": "waygraph test",
10
10
  "fixture": "node scripts/fixture-server.mjs",
11
11
  "graph": "waygraph graph",
12
12
  "map": "waygraph map",
13
13
  "auto:cli": "waygraph auto --cli"
14
14
  },
15
- "waygraph": {
16
- "baseUrl": "http://127.0.0.1:4277"
17
- },
18
15
  "dependencies": {
19
16
  "waygraph": "file:../.."
20
17
  },
@@ -1,5 +1,5 @@
1
1
  // Stands in for this example's real app: serves src/pages/<name>.html at clean URLs (/dashboard, /docs).
2
- // Started and stopped by playwright.config.ts's webServer - waygraph run/demo/auto/test all honor it.
2
+ // Started and stopped by config/waygraph.config.ts's webServer - waygraph run/demo/auto/test all honor it.
3
3
  import { createServer } from "node:http";
4
4
  import { readFileSync, existsSync } from "node:fs";
5
5
  import { join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { Engine } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
2
  import { NavDashboardBlock } from "../map/(app_base)/dashboard/_nav.block.js";
3
3
  import { ClickWidgetBlock } from "../map/(app_base)/dashboard/_methods/click-widget.block.js";
4
4
  import { NavDocsBlock } from "../map/(external)/docs/_nav.block.js";
@@ -6,14 +6,12 @@ import { NavDocsBlock } from "../map/(external)/docs/_nav.block.js";
6
6
  import "../map/(app_base)/dashboard/_page.block.js";
7
7
  import "../map/(external)/docs/_page.block.js";
8
8
 
9
- const engine = new Engine();
10
9
 
11
10
  const homeOrigin = process.env.WAYGRAPH_BASE_URL || "http://127.0.0.1:4277";
12
11
 
13
12
  /**
14
13
  * Same real Blocks, same real Checkpoints, same real fixture server as
15
- * routed-demo.flow.ts - built with `engine.map()` instead of
16
- * `engine.defineFlow([start, ..., end])` to prove the fluent builder
14
+ * routed-demo.flow.ts - built with `engine.map()` to prove the fluent builder
17
15
  * against a real browser/DOM, not just the in-memory fakes
18
16
  * tests/nav/map-builder.spec.ts already covers in the main package.
19
17
  *
@@ -1,4 +1,4 @@
1
- import { Engine, start, end } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
2
  import { NavDashboardBlock } from "../map/(app_base)/dashboard/_nav.block.js";
3
3
  import { ClickWidgetBlock } from "../map/(app_base)/dashboard/_methods/click-widget.block.js";
4
4
  import { NavDocsBlock } from "../map/(external)/docs/_nav.block.js";
@@ -6,7 +6,6 @@ import { NavDocsBlock } from "../map/(external)/docs/_nav.block.js";
6
6
  import "../map/(app_base)/dashboard/_page.block.js";
7
7
  import "../map/(external)/docs/_page.block.js";
8
8
 
9
- const engine = new Engine();
10
9
 
11
10
  /** Smoke: dashboard -> click widget -> docs, all Blocks under the Waygraph Map folder convention. */
12
- export const routedDemoFlow = engine.defineFlow([start, NavDashboardBlock, ClickWidgetBlock, NavDocsBlock, end]);
11
+ export const routedDemoFlow = engine.map().start().gotoPage(NavDashboardBlock).method(ClickWidgetBlock).gotoPage(NavDocsBlock).end();