waygraph 0.15.50 → 0.15.52

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 (559) hide show
  1. package/dist/analysis/graph.d.ts +1 -1
  2. package/dist/analysis/graph.js +10 -15
  3. package/dist/analysis/map-check.js +5 -2
  4. package/dist/analysis/practices-check.d.ts +0 -1
  5. package/dist/analysis/practices-check.js +17 -17
  6. package/dist/auto-session/session.d.ts +1 -1
  7. package/dist/auto-session/session.js +14 -8
  8. package/dist/blocks-select.d.ts +7 -4
  9. package/dist/blocks-select.js +0 -14
  10. package/dist/browser.d.ts +27 -0
  11. package/dist/browser.js +62 -0
  12. package/dist/cli/run-chain.js +5 -0
  13. package/dist/cli/usage.js +14 -1
  14. package/dist/cli.js +10 -1
  15. package/dist/commands/agent-dive-scaffold.d.ts +5 -0
  16. package/dist/commands/agent-dive-scaffold.js +7 -0
  17. package/dist/commands/extensions.d.ts +1 -0
  18. package/dist/commands/extensions.js +22 -0
  19. package/dist/commands/init.js +45 -2
  20. package/dist/commands/test.js +16 -2
  21. package/dist/commands/try.js +2 -1
  22. package/dist/commands/upgrade.d.ts +6 -0
  23. package/dist/commands/upgrade.js +107 -0
  24. package/dist/config.d.ts +47 -3
  25. package/dist/config.js +45 -12
  26. package/dist/core/block.d.ts +12 -0
  27. package/dist/core/block.js +36 -0
  28. package/dist/core/blocks/effect.d.ts +0 -3
  29. package/dist/core/blocks/method.d.ts +0 -6
  30. package/dist/core/blocks/nav.d.ts +11 -3
  31. package/dist/core/blocks/nav.js +8 -0
  32. package/dist/core/blocks/page.d.ts +0 -3
  33. package/dist/core/config.d.ts +5 -0
  34. package/dist/core/engine.d.ts +17 -16
  35. package/dist/core/engine.js +3 -3
  36. package/dist/core/flow.d.ts +17 -0
  37. package/dist/core/flow.js +44 -24
  38. package/dist/core/map-builder.d.ts +3 -3
  39. package/dist/core/map-builder.js +3 -3
  40. package/dist/env-file.d.ts +7 -7
  41. package/dist/env-file.js +29 -16
  42. package/dist/extensions.d.ts +21 -0
  43. package/dist/extensions.js +178 -0
  44. package/dist/highlights/types.d.ts +3 -2
  45. package/dist/index.d.ts +8 -3
  46. package/dist/index.js +4 -1
  47. package/dist/pilot-overlay/overlay-fixtures.d.ts +0 -7
  48. package/dist/pilot-overlay/overlay-fixtures.js +0 -45
  49. package/dist/playwright-config.d.ts +4 -0
  50. package/dist/playwright-config.js +15 -0
  51. package/dist/playwright.config.d.ts +2 -0
  52. package/dist/playwright.config.js +6 -0
  53. package/dist/runner/demo-log.js +1 -7
  54. package/dist/runner/inpage/banner.js +10 -2
  55. package/dist/runner/inpage/core.d.ts +1 -1
  56. package/dist/runner/inpage/core.js +8 -7
  57. package/dist/runner/main.js +27 -15
  58. package/dist/runner/rings.js +0 -49
  59. package/dist/session/auto-explore-run.js +21 -6
  60. package/dist/session/auto-explore.js +6 -4
  61. package/dist/session/step-overlay.js +3 -1
  62. package/dist/traverse/run.js +4 -1
  63. package/dist/types.d.ts +0 -3
  64. package/dist/ui/components/ring.js +1 -0
  65. package/dist/ui/overlay.css +1 -0
  66. package/dist/ui/shadow.d.ts +1 -3
  67. package/dist/ui/shadow.js +0 -4
  68. package/dist/ui/tokens.d.ts +0 -11
  69. package/dist/ui/tokens.js +0 -5
  70. package/dist/video-dir.d.ts +8 -0
  71. package/dist/video-dir.js +60 -0
  72. package/dist/webserver.d.ts +14 -0
  73. package/dist/webserver.js +95 -0
  74. package/examples/routed-demo/package.json +3 -3
  75. package/examples/routed-demo/playwright.config.ts +8 -8
  76. package/examples/routed-demo/scripts/fixture-server.mjs +12 -31
  77. package/examples/routed-demo/src/map/(app_base)/dashboard/_sel.ts +1 -3
  78. package/examples/routed-demo/src/map/(external)/docs/_sel.ts +1 -3
  79. package/examples/routed-demo/src/pages/dashboard.html +1 -1
  80. package/examples/routed-demo/src/pages/docs.html +1 -1
  81. package/examples/saucedemo/playwright.config.ts +2 -3
  82. package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +2 -1
  83. package/examples/saucedemo/scripts/prove-auto-graph.mjs +2 -1
  84. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +2 -1
  85. package/examples/saucedemo/tests/flow-block-verify.spec.ts +2 -7
  86. package/package.json +10 -2
  87. package/templates/quickstart/playwright.config.ts +0 -6
  88. package/templates/scaffold/README.md +7 -3
  89. package/templates/scaffold/STRUCTURE.md +8 -6
  90. package/templates/scaffold/config/waygraph.config.ts +26 -0
  91. package/templates/scaffold/package.json +9 -13
  92. package/templates/scaffold/src/flows/README.md +5 -5
  93. package/templates/scaffold/src/flows/example.flow.ts +31 -17
  94. package/templates/scaffold/src/flows/hoppscotch-auth.flow.ts +35 -0
  95. package/templates/scaffold/src/flows/hoppscotch-get.flow.ts +23 -0
  96. package/templates/scaffold/src/flows/hoppscotch-post.flow.ts +33 -0
  97. package/templates/scaffold/src/flows/mail-verify.flow.ts +36 -75
  98. package/templates/scaffold/src/flows/shop.flow.ts +41 -65
  99. package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +0 -9
  100. package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +0 -5
  101. package/templates/scaffold/src/map/(app_base)/docs/_sel.ts +2 -3
  102. package/templates/scaffold/src/map/(app_base)/docs/{docs.html → index.html} +1 -1
  103. package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -21
  104. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +4 -30
  105. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +2 -19
  106. package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +0 -17
  107. package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +3 -16
  108. package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -14
  109. package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +0 -9
  110. package/templates/scaffold/src/map/(app_base)/home/_sel.ts +4 -4
  111. package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +1 -23
  112. package/templates/scaffold/src/map/(app_base)/index.html +17 -0
  113. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +21 -0
  114. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +19 -0
  115. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +20 -0
  116. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +18 -0
  117. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +21 -0
  118. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +21 -0
  119. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +15 -0
  120. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +20 -0
  121. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +23 -0
  122. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +36 -0
  123. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +17 -0
  124. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +22 -0
  125. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +18 -0
  126. package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +11 -0
  127. package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +36 -0
  128. package/templates/scaffold/src/map/(external)/hoppscotch/_sel.ts +27 -0
  129. package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +10 -0
  130. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +2 -27
  131. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +2 -21
  132. package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +1 -19
  133. package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +1 -11
  134. package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +1 -9
  135. package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +0 -11
  136. package/templates/scaffold/src/states/demo.mem-keys.ts +20 -19
  137. package/templates/scaffold/src/states/demo.mem-stubs.ts +4 -0
  138. package/templates/scaffold/src/states/demo.states.ts +7 -1
  139. package/templates/scaffold/tests/README.md +3 -2
  140. package/templates/scaffold/tests/example.spec.ts +2 -3
  141. package/templates/scaffold/tests/hoppscotch.spec.ts +97 -0
  142. package/templates/scaffold/tests/mail-verify.spec.ts +2 -11
  143. package/templates/scaffold/tsconfig.json +1 -1
  144. package/templates/skills/waygraph-convention.skill.md +37 -6
  145. package/templates/skills/waygraph-pilot.skill.md +5 -6
  146. package/dist/runner/overlay-present.d.ts +0 -8
  147. package/dist/runner/overlay-present.js +0 -57
  148. package/dist/ui/components/banner.d.ts +0 -2
  149. package/dist/ui/components/banner.js +0 -10
  150. package/dist/ui/components/cursor.d.ts +0 -2
  151. package/dist/ui/components/cursor.js +0 -19
  152. package/examples/routed-demo/.waygraph-auto/4d4902b7.log +0 -0
  153. package/examples/routed-demo/.waygraph-auto/51ef462e.log +0 -0
  154. package/examples/routed-demo/.waygraph-auto/71527ad9.log +0 -0
  155. package/examples/routed-demo/.waygraph-auto/ca16778e.log +0 -0
  156. package/examples/routed-demo/scripts/with-fixture.mjs +0 -70
  157. package/examples/saucedemo/.waygraph-auto/00b0c55c.log +0 -22
  158. package/examples/saucedemo/.waygraph-auto/00d147d1.log +0 -21
  159. package/examples/saucedemo/.waygraph-auto/00e5d037.log +0 -5
  160. package/examples/saucedemo/.waygraph-auto/015be8f6.log +0 -6
  161. package/examples/saucedemo/.waygraph-auto/026e188e.log +0 -0
  162. package/examples/saucedemo/.waygraph-auto/02f7dd22.log +0 -20
  163. package/examples/saucedemo/.waygraph-auto/03df352d.log +0 -0
  164. package/examples/saucedemo/.waygraph-auto/0402cfcf.log +0 -6
  165. package/examples/saucedemo/.waygraph-auto/050e5b55.log +0 -0
  166. package/examples/saucedemo/.waygraph-auto/05d76fc3.log +0 -0
  167. package/examples/saucedemo/.waygraph-auto/062b581f.log +0 -20
  168. package/examples/saucedemo/.waygraph-auto/0681582b.log +0 -6
  169. package/examples/saucedemo/.waygraph-auto/07845ed1.log +0 -0
  170. package/examples/saucedemo/.waygraph-auto/07f3e964.log +0 -6
  171. package/examples/saucedemo/.waygraph-auto/0868ae4d.log +0 -0
  172. package/examples/saucedemo/.waygraph-auto/0924ddaa.log +0 -22
  173. package/examples/saucedemo/.waygraph-auto/092d6173.log +0 -5
  174. package/examples/saucedemo/.waygraph-auto/096fea05.log +0 -20
  175. package/examples/saucedemo/.waygraph-auto/09924510.log +0 -0
  176. package/examples/saucedemo/.waygraph-auto/0998c941.log +0 -21
  177. package/examples/saucedemo/.waygraph-auto/0a8c3719.log +0 -0
  178. package/examples/saucedemo/.waygraph-auto/0bf74300.log +0 -21
  179. package/examples/saucedemo/.waygraph-auto/0c01fd29.log +0 -4
  180. package/examples/saucedemo/.waygraph-auto/0c19e232.log +0 -5
  181. package/examples/saucedemo/.waygraph-auto/0c302590.log +0 -0
  182. package/examples/saucedemo/.waygraph-auto/0dee62d6.log +0 -5
  183. package/examples/saucedemo/.waygraph-auto/0eb4c081.log +0 -5
  184. package/examples/saucedemo/.waygraph-auto/0f0cb120.log +0 -0
  185. package/examples/saucedemo/.waygraph-auto/102c38ca.log +0 -0
  186. package/examples/saucedemo/.waygraph-auto/10fd431c.log +0 -0
  187. package/examples/saucedemo/.waygraph-auto/1122c13c.log +0 -0
  188. package/examples/saucedemo/.waygraph-auto/123d1cad.log +0 -5
  189. package/examples/saucedemo/.waygraph-auto/12ed8e28.log +0 -0
  190. package/examples/saucedemo/.waygraph-auto/13c6fe3c.log +0 -0
  191. package/examples/saucedemo/.waygraph-auto/1581b677.log +0 -0
  192. package/examples/saucedemo/.waygraph-auto/161cc8dd.log +0 -22
  193. package/examples/saucedemo/.waygraph-auto/164761a5.log +0 -6
  194. package/examples/saucedemo/.waygraph-auto/1905ceb2.log +0 -0
  195. package/examples/saucedemo/.waygraph-auto/1b1d55c6.log +0 -0
  196. package/examples/saucedemo/.waygraph-auto/1b80fd24.log +0 -6
  197. package/examples/saucedemo/.waygraph-auto/1bd7b7bf.log +0 -0
  198. package/examples/saucedemo/.waygraph-auto/1c30a3c2.log +0 -0
  199. package/examples/saucedemo/.waygraph-auto/1c58a174.log +0 -0
  200. package/examples/saucedemo/.waygraph-auto/1cb6f44c.log +0 -5
  201. package/examples/saucedemo/.waygraph-auto/1d90aa9a.log +0 -0
  202. package/examples/saucedemo/.waygraph-auto/1de7d889.log +0 -0
  203. package/examples/saucedemo/.waygraph-auto/1f233a4c.log +0 -6
  204. package/examples/saucedemo/.waygraph-auto/1fdb2100.log +0 -0
  205. package/examples/saucedemo/.waygraph-auto/20e66801.log +0 -0
  206. package/examples/saucedemo/.waygraph-auto/20e91af6.log +0 -5
  207. package/examples/saucedemo/.waygraph-auto/20ffdb77.log +0 -0
  208. package/examples/saucedemo/.waygraph-auto/22048fff.log +0 -4
  209. package/examples/saucedemo/.waygraph-auto/222d1d09.log +0 -0
  210. package/examples/saucedemo/.waygraph-auto/22f1a704.log +0 -5
  211. package/examples/saucedemo/.waygraph-auto/2324269a.log +0 -0
  212. package/examples/saucedemo/.waygraph-auto/232a1d81.log +0 -0
  213. package/examples/saucedemo/.waygraph-auto/239cced3.log +0 -20
  214. package/examples/saucedemo/.waygraph-auto/25204b46.log +0 -4
  215. package/examples/saucedemo/.waygraph-auto/2553d107.log +0 -0
  216. package/examples/saucedemo/.waygraph-auto/25e2e90f.log +0 -0
  217. package/examples/saucedemo/.waygraph-auto/2708455e.log +0 -22
  218. package/examples/saucedemo/.waygraph-auto/272a96fd.log +0 -20
  219. package/examples/saucedemo/.waygraph-auto/28d7be5d.log +0 -0
  220. package/examples/saucedemo/.waygraph-auto/2a577961.log +0 -0
  221. package/examples/saucedemo/.waygraph-auto/2a6a8266.log +0 -6
  222. package/examples/saucedemo/.waygraph-auto/2b3401cf.log +0 -20
  223. package/examples/saucedemo/.waygraph-auto/2b831907.log +0 -6
  224. package/examples/saucedemo/.waygraph-auto/2b9b56fc.log +0 -20
  225. package/examples/saucedemo/.waygraph-auto/2c79c73a.log +0 -0
  226. package/examples/saucedemo/.waygraph-auto/2c94a05b.log +0 -0
  227. package/examples/saucedemo/.waygraph-auto/2ceccd6d.log +0 -0
  228. package/examples/saucedemo/.waygraph-auto/2e2069e7.log +0 -0
  229. package/examples/saucedemo/.waygraph-auto/2e6bc35e.log +0 -6
  230. package/examples/saucedemo/.waygraph-auto/2efd1983.log +0 -0
  231. package/examples/saucedemo/.waygraph-auto/2f1b0c13.log +0 -6
  232. package/examples/saucedemo/.waygraph-auto/2f4f531e.log +0 -0
  233. package/examples/saucedemo/.waygraph-auto/2f8d4073.log +0 -6
  234. package/examples/saucedemo/.waygraph-auto/2fdbd916.log +0 -0
  235. package/examples/saucedemo/.waygraph-auto/30739278.log +0 -6
  236. package/examples/saucedemo/.waygraph-auto/30a5c848.log +0 -20
  237. package/examples/saucedemo/.waygraph-auto/31cb2e80.log +0 -0
  238. package/examples/saucedemo/.waygraph-auto/322d63cd.log +0 -0
  239. package/examples/saucedemo/.waygraph-auto/3239aa8a.log +0 -6
  240. package/examples/saucedemo/.waygraph-auto/326d87b7.log +0 -6
  241. package/examples/saucedemo/.waygraph-auto/331c6e8e.log +0 -0
  242. package/examples/saucedemo/.waygraph-auto/3351c0b6.log +0 -0
  243. package/examples/saucedemo/.waygraph-auto/33a50dc0.log +0 -0
  244. package/examples/saucedemo/.waygraph-auto/33df0770.log +0 -0
  245. package/examples/saucedemo/.waygraph-auto/340d624d.log +0 -0
  246. package/examples/saucedemo/.waygraph-auto/36367ccf.log +0 -0
  247. package/examples/saucedemo/.waygraph-auto/372536a5.log +0 -6
  248. package/examples/saucedemo/.waygraph-auto/37b56184.log +0 -0
  249. package/examples/saucedemo/.waygraph-auto/38f6799d.log +0 -0
  250. package/examples/saucedemo/.waygraph-auto/3a208bb8.log +0 -20
  251. package/examples/saucedemo/.waygraph-auto/3a412f3c.log +0 -0
  252. package/examples/saucedemo/.waygraph-auto/3a859bd7.log +0 -0
  253. package/examples/saucedemo/.waygraph-auto/3a8674d5.log +0 -6
  254. package/examples/saucedemo/.waygraph-auto/3bdb2f5a.log +0 -0
  255. package/examples/saucedemo/.waygraph-auto/3c1e5fe0.log +0 -22
  256. package/examples/saucedemo/.waygraph-auto/3cb0add7.log +0 -0
  257. package/examples/saucedemo/.waygraph-auto/3e3c0f3b.log +0 -0
  258. package/examples/saucedemo/.waygraph-auto/3e42f0d8.log +0 -0
  259. package/examples/saucedemo/.waygraph-auto/3f088138.log +0 -0
  260. package/examples/saucedemo/.waygraph-auto/401177a3.log +0 -0
  261. package/examples/saucedemo/.waygraph-auto/413d934d.log +0 -0
  262. package/examples/saucedemo/.waygraph-auto/4144071d.log +0 -0
  263. package/examples/saucedemo/.waygraph-auto/4176a3c6.log +0 -0
  264. package/examples/saucedemo/.waygraph-auto/41d0793d.log +0 -4
  265. package/examples/saucedemo/.waygraph-auto/41e6feae.log +0 -0
  266. package/examples/saucedemo/.waygraph-auto/424b4d5d.log +0 -0
  267. package/examples/saucedemo/.waygraph-auto/42e014d1.log +0 -0
  268. package/examples/saucedemo/.waygraph-auto/43253aba.log +0 -0
  269. package/examples/saucedemo/.waygraph-auto/432d09e3.log +0 -22
  270. package/examples/saucedemo/.waygraph-auto/438c6c53.log +0 -22
  271. package/examples/saucedemo/.waygraph-auto/4477db12.log +0 -0
  272. package/examples/saucedemo/.waygraph-auto/47247959.log +0 -0
  273. package/examples/saucedemo/.waygraph-auto/476cff76.log +0 -0
  274. package/examples/saucedemo/.waygraph-auto/4a1258b7.log +0 -0
  275. package/examples/saucedemo/.waygraph-auto/4ad09ece.log +0 -0
  276. package/examples/saucedemo/.waygraph-auto/4adcd179.log +0 -20
  277. package/examples/saucedemo/.waygraph-auto/4c9d9b16.log +0 -21
  278. package/examples/saucedemo/.waygraph-auto/4cebc228.log +0 -20
  279. package/examples/saucedemo/.waygraph-auto/4da39c36.log +0 -6
  280. package/examples/saucedemo/.waygraph-auto/4dbefa7e.log +0 -5
  281. package/examples/saucedemo/.waygraph-auto/4efa7035.log +0 -6
  282. package/examples/saucedemo/.waygraph-auto/505affdc.log +0 -4
  283. package/examples/saucedemo/.waygraph-auto/51bcb60a.log +0 -0
  284. package/examples/saucedemo/.waygraph-auto/527b6d76.log +0 -0
  285. package/examples/saucedemo/.waygraph-auto/5291bc78.log +0 -22
  286. package/examples/saucedemo/.waygraph-auto/535e8922.log +0 -0
  287. package/examples/saucedemo/.waygraph-auto/54274c39.log +0 -5
  288. package/examples/saucedemo/.waygraph-auto/5440ce7e.log +0 -0
  289. package/examples/saucedemo/.waygraph-auto/5738175f.log +0 -22
  290. package/examples/saucedemo/.waygraph-auto/573abedd.log +0 -0
  291. package/examples/saucedemo/.waygraph-auto/57ce5643.log +0 -22
  292. package/examples/saucedemo/.waygraph-auto/5984426b.log +0 -6
  293. package/examples/saucedemo/.waygraph-auto/5a682e7c.log +0 -22
  294. package/examples/saucedemo/.waygraph-auto/5b79320c.log +0 -21
  295. package/examples/saucedemo/.waygraph-auto/5b838485.log +0 -0
  296. package/examples/saucedemo/.waygraph-auto/5c55aaac.log +0 -21
  297. package/examples/saucedemo/.waygraph-auto/5d13bdde.log +0 -0
  298. package/examples/saucedemo/.waygraph-auto/5d285cd3.log +0 -0
  299. package/examples/saucedemo/.waygraph-auto/5ed00b16.log +0 -4
  300. package/examples/saucedemo/.waygraph-auto/60b9c066.log +0 -6
  301. package/examples/saucedemo/.waygraph-auto/610dd127.log +0 -0
  302. package/examples/saucedemo/.waygraph-auto/61105500.log +0 -5
  303. package/examples/saucedemo/.waygraph-auto/61333142.log +0 -5
  304. package/examples/saucedemo/.waygraph-auto/6134afe8.log +0 -20
  305. package/examples/saucedemo/.waygraph-auto/61937e83.log +0 -22
  306. package/examples/saucedemo/.waygraph-auto/625e7f65.log +0 -5
  307. package/examples/saucedemo/.waygraph-auto/62a0bdc9.log +0 -22
  308. package/examples/saucedemo/.waygraph-auto/6376fc15.log +0 -0
  309. package/examples/saucedemo/.waygraph-auto/63b0f4cd.log +0 -0
  310. package/examples/saucedemo/.waygraph-auto/6599cbca.log +0 -22
  311. package/examples/saucedemo/.waygraph-auto/6706ead4.log +0 -0
  312. package/examples/saucedemo/.waygraph-auto/67aaca30.log +0 -0
  313. package/examples/saucedemo/.waygraph-auto/685714af.log +0 -0
  314. package/examples/saucedemo/.waygraph-auto/68b10298.log +0 -0
  315. package/examples/saucedemo/.waygraph-auto/68be5e12.log +0 -0
  316. package/examples/saucedemo/.waygraph-auto/68df05a6.log +0 -22
  317. package/examples/saucedemo/.waygraph-auto/68fa0682.log +0 -0
  318. package/examples/saucedemo/.waygraph-auto/693f67c4.log +0 -20
  319. package/examples/saucedemo/.waygraph-auto/69ae030a.log +0 -6
  320. package/examples/saucedemo/.waygraph-auto/69e73f35.log +0 -6
  321. package/examples/saucedemo/.waygraph-auto/6b2333b0.log +0 -5
  322. package/examples/saucedemo/.waygraph-auto/6c4c3817.log +0 -0
  323. package/examples/saucedemo/.waygraph-auto/6c954911.log +0 -0
  324. package/examples/saucedemo/.waygraph-auto/6d65a439.log +0 -5
  325. package/examples/saucedemo/.waygraph-auto/6d700055.log +0 -0
  326. package/examples/saucedemo/.waygraph-auto/6ead848f.log +0 -0
  327. package/examples/saucedemo/.waygraph-auto/6f05bdc1.log +0 -0
  328. package/examples/saucedemo/.waygraph-auto/70279fc3.log +0 -0
  329. package/examples/saucedemo/.waygraph-auto/70c97639.log +0 -0
  330. package/examples/saucedemo/.waygraph-auto/72675b2d.log +0 -6
  331. package/examples/saucedemo/.waygraph-auto/731a14bd.log +0 -0
  332. package/examples/saucedemo/.waygraph-auto/733dd260.log +0 -5
  333. package/examples/saucedemo/.waygraph-auto/73a41843.log +0 -0
  334. package/examples/saucedemo/.waygraph-auto/75016486.log +0 -0
  335. package/examples/saucedemo/.waygraph-auto/752b01c6.log +0 -22
  336. package/examples/saucedemo/.waygraph-auto/75675227.log +0 -6
  337. package/examples/saucedemo/.waygraph-auto/756fd326.log +0 -20
  338. package/examples/saucedemo/.waygraph-auto/75e2e658.log +0 -0
  339. package/examples/saucedemo/.waygraph-auto/76128a2d.log +0 -0
  340. package/examples/saucedemo/.waygraph-auto/76ac1a86.log +0 -0
  341. package/examples/saucedemo/.waygraph-auto/77605295.log +0 -0
  342. package/examples/saucedemo/.waygraph-auto/7773a809.log +0 -0
  343. package/examples/saucedemo/.waygraph-auto/78043767.log +0 -20
  344. package/examples/saucedemo/.waygraph-auto/792671f4.log +0 -22
  345. package/examples/saucedemo/.waygraph-auto/796ab578.log +0 -0
  346. package/examples/saucedemo/.waygraph-auto/79915adb.log +0 -20
  347. package/examples/saucedemo/.waygraph-auto/7a398774.log +0 -6
  348. package/examples/saucedemo/.waygraph-auto/7a72f66e.log +0 -6
  349. package/examples/saucedemo/.waygraph-auto/7a984334.log +0 -4
  350. package/examples/saucedemo/.waygraph-auto/7b226350.log +0 -5
  351. package/examples/saucedemo/.waygraph-auto/7c6ee793.log +0 -20
  352. package/examples/saucedemo/.waygraph-auto/7c726dc4.log +0 -22
  353. package/examples/saucedemo/.waygraph-auto/7c72e8a5.log +0 -4
  354. package/examples/saucedemo/.waygraph-auto/7c99674f.log +0 -0
  355. package/examples/saucedemo/.waygraph-auto/7dbee625.log +0 -22
  356. package/examples/saucedemo/.waygraph-auto/7df66956.log +0 -0
  357. package/examples/saucedemo/.waygraph-auto/7e053160.log +0 -0
  358. package/examples/saucedemo/.waygraph-auto/7e8a6b62.log +0 -0
  359. package/examples/saucedemo/.waygraph-auto/7effd5b2.log +0 -20
  360. package/examples/saucedemo/.waygraph-auto/7f1b4864.log +0 -0
  361. package/examples/saucedemo/.waygraph-auto/7f94fd02.log +0 -0
  362. package/examples/saucedemo/.waygraph-auto/7fcb512f.log +0 -22
  363. package/examples/saucedemo/.waygraph-auto/7fdd47ee.log +0 -2
  364. package/examples/saucedemo/.waygraph-auto/802a0b5b.log +0 -0
  365. package/examples/saucedemo/.waygraph-auto/80322e0b.log +0 -0
  366. package/examples/saucedemo/.waygraph-auto/80a4978e.log +0 -6
  367. package/examples/saucedemo/.waygraph-auto/81257bf0.log +0 -0
  368. package/examples/saucedemo/.waygraph-auto/81cfe480.log +0 -22
  369. package/examples/saucedemo/.waygraph-auto/832f5add.log +0 -0
  370. package/examples/saucedemo/.waygraph-auto/8337b6ad.log +0 -0
  371. package/examples/saucedemo/.waygraph-auto/8481aa1c.log +0 -0
  372. package/examples/saucedemo/.waygraph-auto/8493928e.log +0 -0
  373. package/examples/saucedemo/.waygraph-auto/849ed45d.log +0 -0
  374. package/examples/saucedemo/.waygraph-auto/84dc6480.log +0 -6
  375. package/examples/saucedemo/.waygraph-auto/853bde43.log +0 -0
  376. package/examples/saucedemo/.waygraph-auto/8598b4c0.log +0 -0
  377. package/examples/saucedemo/.waygraph-auto/859a261d.log +0 -0
  378. package/examples/saucedemo/.waygraph-auto/86350ea6.log +0 -22
  379. package/examples/saucedemo/.waygraph-auto/86bb598a.log +0 -0
  380. package/examples/saucedemo/.waygraph-auto/86d09876.log +0 -22
  381. package/examples/saucedemo/.waygraph-auto/878ad01b.log +0 -4
  382. package/examples/saucedemo/.waygraph-auto/87c88ba5.log +0 -0
  383. package/examples/saucedemo/.waygraph-auto/87cb80ff.log +0 -0
  384. package/examples/saucedemo/.waygraph-auto/880b2e78.log +0 -6
  385. package/examples/saucedemo/.waygraph-auto/88527936.log +0 -5
  386. package/examples/saucedemo/.waygraph-auto/88eda676.log +0 -0
  387. package/examples/saucedemo/.waygraph-auto/893023ea.log +0 -5
  388. package/examples/saucedemo/.waygraph-auto/89416718.log +0 -0
  389. package/examples/saucedemo/.waygraph-auto/8996a857.log +0 -6
  390. package/examples/saucedemo/.waygraph-auto/8a08b68d.log +0 -6
  391. package/examples/saucedemo/.waygraph-auto/8a64ba0f.log +0 -6
  392. package/examples/saucedemo/.waygraph-auto/8b1cc2aa.log +0 -6
  393. package/examples/saucedemo/.waygraph-auto/8b73d13e.log +0 -6
  394. package/examples/saucedemo/.waygraph-auto/8be93021.log +0 -0
  395. package/examples/saucedemo/.waygraph-auto/8d960d31.log +0 -1
  396. package/examples/saucedemo/.waygraph-auto/8d9e5cd2.log +0 -21
  397. package/examples/saucedemo/.waygraph-auto/8e12e34f.log +0 -22
  398. package/examples/saucedemo/.waygraph-auto/8ec7d260.log +0 -0
  399. package/examples/saucedemo/.waygraph-auto/8ed43279.log +0 -0
  400. package/examples/saucedemo/.waygraph-auto/93acae32.log +0 -5
  401. package/examples/saucedemo/.waygraph-auto/94221b2b.log +0 -0
  402. package/examples/saucedemo/.waygraph-auto/96321a08.log +0 -0
  403. package/examples/saucedemo/.waygraph-auto/9742b6c2.log +0 -6
  404. package/examples/saucedemo/.waygraph-auto/9761c4c4.log +0 -6
  405. package/examples/saucedemo/.waygraph-auto/976394cd.log +0 -20
  406. package/examples/saucedemo/.waygraph-auto/982138cf.log +0 -0
  407. package/examples/saucedemo/.waygraph-auto/99cc93eb.log +0 -6
  408. package/examples/saucedemo/.waygraph-auto/9a26134c.log +0 -20
  409. package/examples/saucedemo/.waygraph-auto/9cbfbedc.log +0 -0
  410. package/examples/saucedemo/.waygraph-auto/9d827954.log +0 -20
  411. package/examples/saucedemo/.waygraph-auto/9dc147d2.log +0 -22
  412. package/examples/saucedemo/.waygraph-auto/9dd78c5e.log +0 -0
  413. package/examples/saucedemo/.waygraph-auto/a1ab5d29.log +0 -0
  414. package/examples/saucedemo/.waygraph-auto/a215a395.log +0 -22
  415. package/examples/saucedemo/.waygraph-auto/a23b7086.log +0 -4
  416. package/examples/saucedemo/.waygraph-auto/a35bd5ec.log +0 -0
  417. package/examples/saucedemo/.waygraph-auto/a4b36275.log +0 -0
  418. package/examples/saucedemo/.waygraph-auto/a4f8d355.log +0 -20
  419. package/examples/saucedemo/.waygraph-auto/a68995e9.log +0 -22
  420. package/examples/saucedemo/.waygraph-auto/a6e4f936.log +0 -22
  421. package/examples/saucedemo/.waygraph-auto/a7da862b.log +0 -0
  422. package/examples/saucedemo/.waygraph-auto/a82e2a48.log +0 -0
  423. package/examples/saucedemo/.waygraph-auto/a8645294.log +0 -0
  424. package/examples/saucedemo/.waygraph-auto/a94738b7.log +0 -0
  425. package/examples/saucedemo/.waygraph-auto/a952eb91.log +0 -0
  426. package/examples/saucedemo/.waygraph-auto/a9559653.log +0 -5
  427. package/examples/saucedemo/.waygraph-auto/aa1beafb.log +0 -0
  428. package/examples/saucedemo/.waygraph-auto/aa226dd0.log +0 -22
  429. package/examples/saucedemo/.waygraph-auto/aa478de2.log +0 -0
  430. package/examples/saucedemo/.waygraph-auto/aa7323f8.log +0 -20
  431. package/examples/saucedemo/.waygraph-auto/aaae4fb0.log +0 -20
  432. package/examples/saucedemo/.waygraph-auto/ac350fc7.log +0 -20
  433. package/examples/saucedemo/.waygraph-auto/ac5dde3d.log +0 -0
  434. package/examples/saucedemo/.waygraph-auto/acc1b63a.log +0 -0
  435. package/examples/saucedemo/.waygraph-auto/ad0bfad9.log +0 -5
  436. package/examples/saucedemo/.waygraph-auto/ad12d191.log +0 -0
  437. package/examples/saucedemo/.waygraph-auto/ae3a9b06.log +0 -0
  438. package/examples/saucedemo/.waygraph-auto/af2fae12.log +0 -0
  439. package/examples/saucedemo/.waygraph-auto/b04638f4.log +0 -6
  440. package/examples/saucedemo/.waygraph-auto/b0752c49.log +0 -0
  441. package/examples/saucedemo/.waygraph-auto/b14811d7.log +0 -6
  442. package/examples/saucedemo/.waygraph-auto/b2d2dbb2.log +0 -22
  443. package/examples/saucedemo/.waygraph-auto/b3d172f3.log +0 -0
  444. package/examples/saucedemo/.waygraph-auto/b48863e5.log +0 -22
  445. package/examples/saucedemo/.waygraph-auto/b5569336.log +0 -0
  446. package/examples/saucedemo/.waygraph-auto/b56968e1.log +0 -6
  447. package/examples/saucedemo/.waygraph-auto/b57921c5.log +0 -0
  448. package/examples/saucedemo/.waygraph-auto/b64e0620.log +0 -20
  449. package/examples/saucedemo/.waygraph-auto/b75168f7.log +0 -1
  450. package/examples/saucedemo/.waygraph-auto/b86a6218.log +0 -6
  451. package/examples/saucedemo/.waygraph-auto/b8e9e956.log +0 -22
  452. package/examples/saucedemo/.waygraph-auto/b9ab0983.log +0 -0
  453. package/examples/saucedemo/.waygraph-auto/b9b310ff.log +0 -21
  454. package/examples/saucedemo/.waygraph-auto/bb0e0e46.log +0 -0
  455. package/examples/saucedemo/.waygraph-auto/bc111745.log +0 -22
  456. package/examples/saucedemo/.waygraph-auto/bf7a77a2.log +0 -0
  457. package/examples/saucedemo/.waygraph-auto/bf85a598.log +0 -0
  458. package/examples/saucedemo/.waygraph-auto/bf8693e7.log +0 -0
  459. package/examples/saucedemo/.waygraph-auto/c0d6f353.log +0 -21
  460. package/examples/saucedemo/.waygraph-auto/c0febcf2.log +0 -20
  461. package/examples/saucedemo/.waygraph-auto/c4c52998.log +0 -6
  462. package/examples/saucedemo/.waygraph-auto/c52bac6d.log +0 -0
  463. package/examples/saucedemo/.waygraph-auto/c60cc55e.log +0 -0
  464. package/examples/saucedemo/.waygraph-auto/c809ceb4.log +0 -22
  465. package/examples/saucedemo/.waygraph-auto/c851cc53.log +0 -6
  466. package/examples/saucedemo/.waygraph-auto/c8987b67.log +0 -0
  467. package/examples/saucedemo/.waygraph-auto/c9d76e32.log +0 -0
  468. package/examples/saucedemo/.waygraph-auto/ca6de7e7.log +0 -0
  469. package/examples/saucedemo/.waygraph-auto/ca8561bc.log +0 -0
  470. package/examples/saucedemo/.waygraph-auto/cae91469.log +0 -0
  471. package/examples/saucedemo/.waygraph-auto/cb05d223.log +0 -0
  472. package/examples/saucedemo/.waygraph-auto/cb86d45b.log +0 -0
  473. package/examples/saucedemo/.waygraph-auto/cb9a1978.log +0 -6
  474. package/examples/saucedemo/.waygraph-auto/cbbc689c.log +0 -6
  475. package/examples/saucedemo/.waygraph-auto/cc989184.log +0 -20
  476. package/examples/saucedemo/.waygraph-auto/cd88364b.log +0 -0
  477. package/examples/saucedemo/.waygraph-auto/cd919e1d.log +0 -0
  478. package/examples/saucedemo/.waygraph-auto/ce584949.log +0 -5
  479. package/examples/saucedemo/.waygraph-auto/cf34b895.log +0 -2
  480. package/examples/saucedemo/.waygraph-auto/cfff9eef.log +0 -20
  481. package/examples/saucedemo/.waygraph-auto/d0f59b21.log +0 -4
  482. package/examples/saucedemo/.waygraph-auto/d1195079.log +0 -20
  483. package/examples/saucedemo/.waygraph-auto/d2ef067a.log +0 -5
  484. package/examples/saucedemo/.waygraph-auto/d37719a6.log +0 -0
  485. package/examples/saucedemo/.waygraph-auto/d425471f.log +0 -6
  486. package/examples/saucedemo/.waygraph-auto/d4afe93f.log +0 -5
  487. package/examples/saucedemo/.waygraph-auto/d50e58f0.log +0 -0
  488. package/examples/saucedemo/.waygraph-auto/d5293921.log +0 -0
  489. package/examples/saucedemo/.waygraph-auto/d62a22c2.log +0 -21
  490. package/examples/saucedemo/.waygraph-auto/d6d1761f.log +0 -22
  491. package/examples/saucedemo/.waygraph-auto/d6d5f411.log +0 -22
  492. package/examples/saucedemo/.waygraph-auto/d6df2771.log +0 -6
  493. package/examples/saucedemo/.waygraph-auto/d7075012.log +0 -21
  494. package/examples/saucedemo/.waygraph-auto/d846cd78.log +0 -0
  495. package/examples/saucedemo/.waygraph-auto/d934da78.log +0 -0
  496. package/examples/saucedemo/.waygraph-auto/d9ddc297.log +0 -0
  497. package/examples/saucedemo/.waygraph-auto/da0a06bf.log +0 -0
  498. package/examples/saucedemo/.waygraph-auto/da6ebb31.log +0 -0
  499. package/examples/saucedemo/.waygraph-auto/db4ac845.log +0 -0
  500. package/examples/saucedemo/.waygraph-auto/db6d7774.log +0 -0
  501. package/examples/saucedemo/.waygraph-auto/db81ba7d.log +0 -0
  502. package/examples/saucedemo/.waygraph-auto/db839827.log +0 -5
  503. package/examples/saucedemo/.waygraph-auto/dc58eb72.log +0 -0
  504. package/examples/saucedemo/.waygraph-auto/dddd057c.log +0 -20
  505. package/examples/saucedemo/.waygraph-auto/dde5e859.log +0 -22
  506. package/examples/saucedemo/.waygraph-auto/ddf975e6.log +0 -0
  507. package/examples/saucedemo/.waygraph-auto/de8cac58.log +0 -0
  508. package/examples/saucedemo/.waygraph-auto/de8cb83d.log +0 -6
  509. package/examples/saucedemo/.waygraph-auto/ded5511a.log +0 -6
  510. package/examples/saucedemo/.waygraph-auto/dedfcb18.log +0 -0
  511. package/examples/saucedemo/.waygraph-auto/def4d9b1.log +0 -0
  512. package/examples/saucedemo/.waygraph-auto/e03cfd8e.log +0 -0
  513. package/examples/saucedemo/.waygraph-auto/e1549e40.log +0 -0
  514. package/examples/saucedemo/.waygraph-auto/e1b0676d.log +0 -21
  515. package/examples/saucedemo/.waygraph-auto/e230f24e.log +0 -0
  516. package/examples/saucedemo/.waygraph-auto/e5111463.log +0 -0
  517. package/examples/saucedemo/.waygraph-auto/e5127c03.log +0 -22
  518. package/examples/saucedemo/.waygraph-auto/e5fc1d7c.log +0 -5
  519. package/examples/saucedemo/.waygraph-auto/e6fd2202.log +0 -0
  520. package/examples/saucedemo/.waygraph-auto/eb38d92e.log +0 -22
  521. package/examples/saucedemo/.waygraph-auto/edaa806d.log +0 -0
  522. package/examples/saucedemo/.waygraph-auto/edaf33de.log +0 -0
  523. package/examples/saucedemo/.waygraph-auto/edd40cbb.log +0 -20
  524. package/examples/saucedemo/.waygraph-auto/eddfbffc.log +0 -6
  525. package/examples/saucedemo/.waygraph-auto/ee86203e.log +0 -0
  526. package/examples/saucedemo/.waygraph-auto/ee9fa1ad.log +0 -5
  527. package/examples/saucedemo/.waygraph-auto/ef319474.log +0 -22
  528. package/examples/saucedemo/.waygraph-auto/f1f38eeb.log +0 -22
  529. package/examples/saucedemo/.waygraph-auto/f24b2915.log +0 -0
  530. package/examples/saucedemo/.waygraph-auto/f28eee8d.log +0 -0
  531. package/examples/saucedemo/.waygraph-auto/f2943898.log +0 -0
  532. package/examples/saucedemo/.waygraph-auto/f33bde90.log +0 -0
  533. package/examples/saucedemo/.waygraph-auto/f43de83c.log +0 -0
  534. package/examples/saucedemo/.waygraph-auto/f6ba7cb4.log +0 -6
  535. package/examples/saucedemo/.waygraph-auto/f7ac4d62.log +0 -20
  536. package/examples/saucedemo/.waygraph-auto/f86224c6.log +0 -0
  537. package/examples/saucedemo/.waygraph-auto/f929bb79.log +0 -0
  538. package/examples/saucedemo/.waygraph-auto/f92d4c6c.log +0 -22
  539. package/examples/saucedemo/.waygraph-auto/f92faf40.log +0 -5
  540. package/examples/saucedemo/.waygraph-auto/fa784369.log +0 -21
  541. package/examples/saucedemo/.waygraph-auto/fb55f723.log +0 -20
  542. package/examples/saucedemo/.waygraph-auto/fba3b738.log +0 -0
  543. package/examples/saucedemo/.waygraph-auto/fc917c18.log +0 -0
  544. package/examples/saucedemo/.waygraph-auto/fdf66b74.log +0 -0
  545. package/examples/saucedemo/.waygraph-auto/fe83305d.log +0 -0
  546. package/examples/saucedemo/.waygraph-auto/ff616932.log +0 -0
  547. package/examples/saucedemo/.waygraph-auto/ffdf2854.log +0 -6
  548. package/examples/saucedemo/scripts/capture-auto-headful.mjs +0 -120
  549. package/examples/saucedemo/scripts/capture-wrong-login.mjs +0 -141
  550. package/examples/saucedemo/scripts/demo-device-presets.mjs +0 -188
  551. package/examples/saucedemo/scripts/demo-orientation-gestures-video.mjs +0 -262
  552. package/examples/saucedemo/scripts/show-add-to-cart-menu.mjs +0 -123
  553. package/examples/saucedemo/scripts/show-auto-menu.mjs +0 -72
  554. package/templates/scaffold/playwright.config.ts +0 -28
  555. package/templates/scaffold/scripts/README.md +0 -13
  556. package/templates/scaffold/scripts/fixture-server.mjs +0 -50
  557. package/templates/scaffold/scripts/with-fixture.mjs +0 -69
  558. package/templates/scaffold/test-results/.last-run.json +0 -4
  559. /package/templates/scaffold/src/map/(app_base)/home/{home.html → index.html} +0 -0
@@ -101,28 +101,36 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
101
101
  );
102
102
  };
103
103
  const home = b.dataset.home || b.dataset.pos || "left";
104
+ // Called every animation frame while a ring is followed - only log when the outcome changes.
105
+ const log = (state, line) => {
106
+ if (b.dataset.lastLog === state) return;
107
+ b.dataset.lastLog = state;
108
+ if (line) (window.__wgBannerLog = window.__wgBannerLog || []).push(line);
109
+ };
104
110
  b.dataset.pos = home;
105
111
  if (!hits()) {
106
112
  delete b.dataset.moved;
113
+ log("clear");
107
114
  return;
108
115
  }
109
116
  for (const cand of POSITIONS.filter((p) => p !== home)) {
110
117
  b.dataset.pos = cand;
111
118
  if (!hits()) {
112
119
  b.dataset.moved = home + ">" + cand;
113
- (window.__wgBannerLog = window.__wgBannerLog || []).push("moved " + home + " -> " + cand + " (ring overlap)");
120
+ log("moved:" + cand, "moved " + home + " -> " + cand + " (ring overlap)");
114
121
  return;
115
122
  }
116
123
  }
117
124
  b.dataset.pos = home;
118
125
  b.dataset.moved = "none-free";
119
- (window.__wgBannerLog = window.__wgBannerLog || []).push("overlap at every position (kept " + home + ")");
126
+ log("none-free", "overlap at every position (kept " + home + ")");
120
127
  };
121
128
  window.__wgBannerRestore = () => {
122
129
  const b = __wgById("wg-banner");
123
130
  if (!b) return;
124
131
  if (b.dataset.home) b.dataset.pos = b.dataset.home;
125
132
  delete b.dataset.moved;
133
+ delete b.dataset.lastLog;
126
134
  };
127
135
  // Dim the banner while a ring caption is the focus - same "auto opacity" effect the todo
128
136
  // dock already has via __wgTodosSetBehind, extended to the banner so both floating chrome
@@ -1,4 +1,4 @@
1
1
  /** In-page installer (page.evaluate target) - see core.js's own header. Installs the shared ring
2
- * primitive (__wgEnsureRingEl/__wgPaintRingAt/__wgHideRingAt), cursor, click-pulse, focus veil,
2
+ * primitive (__wgEnsureRingEl/__wgPaintRingAt), cursor, click-pulse, focus veil,
3
3
  * and the #wg-ring singleton every surface's "current action" ring uses. */
4
4
  export function installCore(args: Record<string, unknown>): void;
@@ -72,7 +72,14 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
72
72
  ring.style.width = width + "px";
73
73
  ring.style.height = height + "px";
74
74
  ring.style.opacity = "1";
75
- ringLabel.textContent = label || "";
75
+ if (labelId === "wg-ring-label") {
76
+ // The demo ring's caption is drawn from data-label (CSS ::after), not DOM text, so the page's own
77
+ // text selectors (getByText, text=...) never match waygraph's overlay twice.
78
+ ringLabel.dataset.label = label || "";
79
+ ringLabel.textContent = "";
80
+ } else {
81
+ ringLabel.textContent = label || "";
82
+ }
76
83
  ringLabel.style.opacity = "1";
77
84
  const lw = ringLabel.offsetWidth;
78
85
  const lh = ringLabel.offsetHeight;
@@ -104,12 +111,6 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
104
111
  ringLabel.style.top = labelTop + "px";
105
112
  return [ring, ringLabel];
106
113
  };
107
- window.__wgHideRingAt = (ringId, labelId) => {
108
- const ring = __wgById(ringId);
109
- const label = __wgById(labelId);
110
- if (ring) ring.style.opacity = "0";
111
- if (label) label.style.opacity = "0";
112
- };
113
114
  window.__wgEnsureRingEl("wg-ring", "wg-ring-label");
114
115
  if (!__wgById("wg-cursor")) {
115
116
  const cursor = document.createElement("div");
@@ -9,8 +9,11 @@ import { runStepMode } from "./step-mode.js";
9
9
  import { connect } from "../types.js";
10
10
  import { MemPage } from "../mem-page.js";
11
11
  import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../core.js";
12
+ import { withWebServer } from "../webserver.js";
13
+ import { resolveVideoDir } from "../video-dir.js";
14
+ import { chromiumExecutablePath, extensionPathsFromEnv, launchContext } from "../browser.js";
12
15
 
13
- async function main() {
16
+ async function runMain() {
14
17
  const projectDir = process.argv[2];
15
18
  const spec = process.argv[3];
16
19
  const mem = new MemPage();
@@ -250,7 +253,7 @@ async function main() {
250
253
  const videoEnv = process.env.WAYGRAPH_VIDEO;
251
254
  let videoDir = null;
252
255
  if (videoEnv) {
253
- videoDir = videoEnv === "1" ? join(projectDir, ".waygraph-videos") : videoEnv;
256
+ videoDir = videoEnv === "1" ? await resolveVideoDir(projectDir) : videoEnv;
254
257
  mkdirSync(videoDir, { recursive: true });
255
258
  }
256
259
  /** Fixed 16:9 capture for --video (demo QA and headless run). Step+video no longer maximizes. */
@@ -285,19 +288,9 @@ async function main() {
285
288
  // launched at Chromium's own default size/position, which stayed put
286
289
  // where it was for a previous, larger monitor and looked chopped off on
287
290
  // a smaller one. Maximizing fills whatever screen it's actually on.
288
- // Same CHROME_PATH/CHROMIUM_PATH rule as Engine.run(mem): prefer the
289
- // system/Flatpak Chromium when set, otherwise Playwright's bundled build.
290
- // Without this, STEP mode always launched a different-looking browser than
291
- // headed Engine runs / waygraph-demo.mjs (which already resolve Flatpak).
292
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH || undefined;
291
+ const executablePath = chromiumExecutablePath();
293
292
  // Maximized for interactive step, and for fixed video viewport so the
294
293
  // locked record size can actually fit (otherwise .webm gets grey pad).
295
- const browser = await chromium.launch({
296
- headless: !headed,
297
- slowMo,
298
- args: step || fixedVideoViewport ? ["--start-maximized"] : [],
299
- ...(executablePath ? { executablePath } : {}),
300
- });
301
294
  const contextOpts = fixedVideoViewport
302
295
  ? {
303
296
  baseURL,
@@ -315,7 +308,17 @@ async function main() {
315
308
  ? { dir: videoDir, size: fixedVideoViewport }
316
309
  : { dir: videoDir };
317
310
  }
318
- const context = await browser.newContext(contextOpts);
311
+ const { context, close: closeBrowser } = await launchContext({
312
+ launcher: chromium,
313
+ launch: {
314
+ headless: !headed,
315
+ slowMo,
316
+ args: step || fixedVideoViewport ? ["--start-maximized"] : [],
317
+ ...(executablePath ? { executablePath } : {}),
318
+ },
319
+ context: contextOpts,
320
+ extensions: extensionPathsFromEnv(),
321
+ });
319
322
  let pageForVideo = null;
320
323
  try {
321
324
  if (step) {
@@ -371,7 +374,7 @@ async function main() {
371
374
  if (savedVideo) {
372
375
  console.log("waygraph: video saved to " + savedVideo);
373
376
  }
374
- await browser.close();
377
+ await closeBrowser();
375
378
  }
376
379
  } else {
377
380
  if (chainFlows && chainFlows.length > 0) {
@@ -423,6 +426,9 @@ async function runAllBranchesMode(chainFlows, mem, baseURL, headed, engine) {
423
426
  process.exitCode = 1;
424
427
  return;
425
428
  }
429
+ if (extensionPathsFromEnv().length > 0) {
430
+ console.warn("waygraph run --all-branches: extensions are not loaded (branches run in cloned contexts)");
431
+ }
426
432
  const { chromium } = await import("@playwright/test");
427
433
  const browser = await chromium.launch({ headless: !headed });
428
434
  const cloneSession = process.env.WAYGRAPH_SHARED_SESSION !== "1";
@@ -446,6 +452,12 @@ async function runAllBranchesMode(chainFlows, mem, baseURL, headed, engine) {
446
452
  void engine;
447
453
  }
448
454
 
455
+ // Here, not in the host CLI: importing playwright.config loads the project's own @playwright/test,
456
+ // which would collide with the CLI's copy.
457
+ async function main() {
458
+ await withWebServer(process.argv[2], runMain);
459
+ }
460
+
449
461
  export function startRunner() {
450
462
  main().catch((err) => {
451
463
  console.error(err && err.stack ? err.stack : String(err));
@@ -381,55 +381,6 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
381
381
  }
382
382
 
383
383
 
384
- /**
385
- * Paint a NAMED ring instance (ui/css/ring.css's shared `.wg-ring-el`/`.wg-ring-el-label`) at a
386
- * known viewport box - the primitive both the demo/auto singleton (`showRing`, always "wg-ring")
387
- * and Pilot's several simultaneous fixture rings (their own ids) paint through, so there is one
388
- * ring-rendering implementation, not two. No collision/follow/focus - those are `#wg-ring`'s own
389
- * extras (see `showRing`/`inpage/core.js`'s `__wgPositionRing`), meaningless for an independent
390
- * fixture ring that isn't "the current action."
391
- */
392
- export async function showRingAt(page, ringId, labelId, box, label, tone, style) {
393
- const size = normalizeHighlightSize(style && style.size);
394
- const weight = normalizeHighlightWeight(style && style.weight);
395
- const color = style && style.color ? String(style.color) : "";
396
- await page
397
- .evaluate(
398
- ({ ringId, labelId, box, label, tone, size, weight, color }) => {
399
- if (window.__wgPaintRingAt) {
400
- window.__wgPaintRingAt(ringId, labelId, box, label, tone, { size, weight, color });
401
- }
402
- },
403
- { ringId, labelId, box, label, tone: tone || "planned", size, weight, color },
404
- )
405
- .catch(() => {});
406
- }
407
-
408
- /** Hide (not remove) a named ring instance painted via {@link showRingAt}. */
409
- export async function hideRingAt(page, ringId, labelId) {
410
- await page
411
- .evaluate(
412
- ({ ringId, labelId }) => {
413
- if (window.__wgHideRingAt) window.__wgHideRingAt(ringId, labelId);
414
- },
415
- { ringId, labelId },
416
- )
417
- .catch(() => {});
418
- }
419
-
420
- /** Remove a named ring instance entirely (Pilot's fixture rings are short-lived, not reused). */
421
- export async function removeRingAt(page, ringId, labelId) {
422
- await page
423
- .evaluate(
424
- ({ ringId, labelId }) => {
425
- __wgById(ringId)?.remove();
426
- __wgById(labelId)?.remove();
427
- },
428
- { ringId, labelId },
429
- )
430
- .catch(() => {});
431
- }
432
-
433
384
  export async function showRing(page, box, label, tone, style) {
434
385
  const size = normalizeHighlightSize(style && style.size);
435
386
  const weight = normalizeHighlightWeight(style && style.weight);
@@ -5,7 +5,9 @@ import { Engine, start, end, locate } from "../core.js";
5
5
  import { MemPage } from "../mem-page.js";
6
6
  import { buildExploreContext, buildExploreMenu, } from "./auto-explore.js";
7
7
  import { installDemoChrome, instrumentInteractionHighlighting } from "./step-overlay.js";
8
- import { resolveBaseUrl } from "../config.js";
8
+ import { configuredExtensions, resolveBaseUrl } from "../config.js";
9
+ import { withWebServer } from "../webserver.js";
10
+ import { chromiumExecutablePath, launchContext } from "../browser.js";
9
11
  /** See `../config.js`'s own `resolveBaseUrl` - re-exported so existing importers of this module
10
12
  * don't need to change their import path. */
11
13
  export { resolveBaseUrl };
@@ -540,7 +542,13 @@ function printCliMenu(menu, library) {
540
542
  }
541
543
  async function cliPick(menu, rl) {
542
544
  while (true) {
543
- const ans = (await rl.question("Choose: ")).trim().toLowerCase();
545
+ let ans;
546
+ try {
547
+ ans = (await rl.question("Choose: ")).trim().toLowerCase();
548
+ }
549
+ catch {
550
+ return { type: "quit" }; // stdin ended (piped / Ctrl-D) - same as q
551
+ }
544
552
  if (ans === "q" || ans === "quit")
545
553
  return { type: "quit" };
546
554
  const n = Number(ans);
@@ -554,6 +562,9 @@ async function cliPick(menu, rl) {
554
562
  * Interactive waygraph auto: locate current Checkpoint, list runnable Blocks, pick one, repeat.
555
563
  */
556
564
  export async function runAutoExplore(projectDir, options = {}) {
565
+ await withWebServer(projectDir, () => runAutoExploreCore(projectDir, options));
566
+ }
567
+ async function runAutoExploreCore(projectDir, options = {}) {
557
568
  lastRunNote = null;
558
569
  const cli = options.cli === true;
559
570
  const baseURL = options.baseURL ?? (await resolveBaseUrl(projectDir)) ?? process.env.WAYGRAPH_BASE_URL;
@@ -567,7 +578,7 @@ export async function runAutoExplore(projectDir, options = {}) {
567
578
  seedDefaultMem(library.byName, mem);
568
579
  const engine = cli ? new Engine({ headless: true }) : new Engine({ headless: false, slowMo: 250 });
569
580
  const { chromium } = await import("@playwright/test");
570
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
581
+ const executablePath = chromiumExecutablePath();
571
582
  const launchOpts = {
572
583
  headless: cli,
573
584
  args: cli ? [] : ["--start-maximized"],
@@ -576,13 +587,17 @@ export async function runAutoExplore(projectDir, options = {}) {
576
587
  launchOpts.slowMo = 250;
577
588
  if (executablePath)
578
589
  launchOpts.executablePath = executablePath;
579
- const browser = await chromium.launch(launchOpts);
580
590
  const contextOpts = cli
581
591
  ? { viewport: { width: 1280, height: 720 } }
582
592
  : { viewport: null };
583
593
  if (baseURL)
584
594
  contextOpts.baseURL = baseURL;
585
- const context = await browser.newContext(contextOpts);
595
+ const { close: closeBrowser, context } = await launchContext({
596
+ launcher: chromium,
597
+ launch: launchOpts,
598
+ context: contextOpts,
599
+ extensions: await configuredExtensions(projectDir),
600
+ });
586
601
  let page = await context.newPage();
587
602
  if (startUrl) {
588
603
  await page.goto(startUrl, { waitUntil: "domcontentloaded" }).catch(() => { });
@@ -681,6 +696,6 @@ export async function runAutoExplore(projectDir, options = {}) {
681
696
  finally {
682
697
  cliRl?.close();
683
698
  await context.close();
684
- await browser.close();
699
+ await closeBrowser();
685
700
  }
686
701
  }
@@ -169,7 +169,7 @@ export function exploreChoices(graph, here) {
169
169
  const out = [];
170
170
  for (const edge of graph.edges) {
171
171
  if (here === null) {
172
- if (edge.kind !== "nav")
172
+ if (edge.kind !== "nav" || edge.from !== "*")
173
173
  continue;
174
174
  }
175
175
  else if (edge.from !== here && edge.from !== "*") {
@@ -283,8 +283,9 @@ export async function buildExploreMenu(page, graph, library, here) {
283
283
  continue;
284
284
  if (here === null) {
285
285
  // Bootstrap only: URL deep-links as "Start here". Click-nav needs a live
286
- // control so it cannot seed an unknown page.
287
- if (!isUrlNav(entry))
286
+ // control so it cannot seed an unknown page, and a Nav with `from` needs
287
+ // that state first (e.g. signed in) so it cannot start one either.
288
+ if (!isUrlNav(entry) || edge.from !== "*")
288
289
  continue;
289
290
  push(navigate, edge);
290
291
  continue;
@@ -295,7 +296,8 @@ export async function buildExploreMenu(page, graph, library, here) {
295
296
  // Graph still marks NavBlocks from:"*" for pathfinding/traverse; auto menu
296
297
  // only offers click-nav whose control is visible on this page (navRunnable).
297
298
  // Otherwise LoginForm lists every app route + mailpit as if legal moves.
298
- if (isUrlNav(entry))
299
+ // A url Nav that declares `from` is only an edge from those pages, so it IS a real move here.
300
+ if (isUrlNav(entry) && edge.from === "*")
299
301
  continue;
300
302
  if (isBackEdge(edge) && (edge.from === here || edge.from === "*")) {
301
303
  push(back, edge);
@@ -86,7 +86,9 @@ export async function installDemoChrome(page, title = "waygraph auto", options =
86
86
  ring.style.width = box.width + pad * 2 + "px";
87
87
  ring.style.height = box.height + pad * 2 + "px";
88
88
  ring.style.opacity = "1";
89
- ringLabel.textContent = label;
89
+ // Drawn from data-label (CSS ::after), not DOM text, so the page's own text selectors never match it.
90
+ ringLabel.dataset.label = label;
91
+ ringLabel.textContent = "";
90
92
  ringLabel.style.left = box.x + "px";
91
93
  ringLabel.style.top = box.y + box.height + 8 + "px";
92
94
  ringLabel.style.opacity = "1";
@@ -5,6 +5,7 @@ import { defaultMemValueForKey } from "../session/auto-explore-run.js";
5
5
  import { resolveBaseUrl } from "../config.js";
6
6
  import { EdgeLeaseCoordinator } from "./lease.js";
7
7
  import { buildCoverageReport, collectGraphEdgeKeys, defaultCoverageOutPath, formatCoverageLine, writeCoverageReport, } from "./coverage.js";
8
+ import { chromiumExecutablePath } from "../browser.js";
8
9
  function seedMem(library, mem, dataJson) {
9
10
  const raw = dataJson ?? process.env.WAYGRAPH_DATA ?? process.env.WAYGRAPH_AUTO_MEM;
10
11
  let envParsed = {};
@@ -252,8 +253,10 @@ export async function runTraverse(projectDir, options = {}) {
252
253
  const allEdgeKeys = collectGraphEdgeKeys(graph.edges);
253
254
  const leases = new EdgeLeaseCoordinator({ projectDir, persist: parallel > 1 });
254
255
  const engine = new Engine({ headless: !headed, slowMo: headed ? 100 : 0 });
256
+ if (process.env.WAYGRAPH_EXTENSIONS)
257
+ console.error("waygraph traverse: extensions are not loaded (workers use plain contexts)");
255
258
  const { chromium } = await import("@playwright/test");
256
- const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
259
+ const executablePath = chromiumExecutablePath();
257
260
  const launchOpts = {
258
261
  headless: !headed,
259
262
  };
package/dist/types.d.ts CHANGED
@@ -284,15 +284,12 @@ export type DefinedBlock<In extends Checkpoint<string>, Out extends Checkpoint<s
284
284
  */
285
285
  stubBefore(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
286
286
  stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
287
- stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
288
287
  /** Demo narration after resolve. Prefer ctx callbacks over slot-map objects. */
289
288
  stubAfter(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
290
289
  stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
291
- stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
292
290
  /** Demo narration when the step fails / expected-failure path. */
293
291
  stubOnError(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
294
292
  stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
295
- stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
296
293
  };
297
294
  /**
298
295
  * Structural (not imported) twin of `engine.ts`'s `Layout` - `types.ts` sits
@@ -20,6 +20,7 @@ export function ringCss() {
20
20
  "#wg-ring-label{position:fixed;z-index:2147483646;pointer-events:none;opacity:0;" +
21
21
  `max-width:min(360px,70vw);white-space:normal;padding:6px 10px;border-radius:7px;background:${p.labelBg};color:${p.labelFg};` +
22
22
  "font:600 12px/1.35 system-ui,sans-serif;transition:opacity .3s ease;}" +
23
+ "#wg-ring-label::after{content:attr(data-label);}" +
23
24
  toneRules("#wg-ring-label", (t) => `background:${t.labelBg};color:${t.labelFg};`) +
24
25
  // Gray = a real Playwright-driven instruction: mark it with a robot.
25
26
  `#wg-ring-label[data-tone=auto]::before{${ROBOT}}` +
@@ -86,6 +86,7 @@
86
86
  font: 600 12px/1.35 var(--wg-font); transition: opacity .3s ease;
87
87
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; box-shadow: 0 2px 8px rgba(0,0,0,.25);
88
88
  }
89
+ #wg-ring-label::after { content: attr(data-label); }
89
90
  .wg-ring-el-label[data-tone=planned] { --wg-tone-bg: var(--wg-tone-planned-bg); --wg-tone-fg: var(--wg-tone-planned-fg); }
90
91
  .wg-ring-el-label[data-tone=auto] { --wg-tone-bg: var(--wg-tone-auto-bg); --wg-tone-fg: var(--wg-tone-auto-fg); }
91
92
  .wg-ring-el-label[data-tone=info] { --wg-tone-bg: var(--wg-tone-info-bg); --wg-tone-fg: var(--wg-tone-info-fg); }
@@ -7,7 +7,7 @@
7
7
  * lookups check the shadow root first and fall back to the light DOM (the device stage shell and
8
8
  * host-page markers such as `[data-wg-zoomed]` intentionally stay in the light DOM).
9
9
  */
10
- import type { BrowserContext, Page } from "@playwright/test";
10
+ import type { Page } from "@playwright/test";
11
11
  /**
12
12
  * `overlaySheet` is the ONE real-CSS bundle (`ui/stylesheet.ts` -> `dist/ui/overlay.css`, built on
13
13
  * Open Props - see `src/ui/css/README.md`) every surface shares; passed in from Node since in-page
@@ -16,5 +16,3 @@ import type { BrowserContext, Page } from "@playwright/test";
16
16
  export declare function installShadowRoot(overlaySheet?: string): void;
17
17
  /** Idempotent; call before any overlay install on a page. Installs the shared stylesheet bundle. */
18
18
  export declare function ensureShadowRoot(page: Page): Promise<void>;
19
- /** Also define the helpers on every future document (pilot overlay persists across navigations). */
20
- export declare function installShadowRootEverywhere(context: BrowserContext): Promise<void>;
package/dist/ui/shadow.js CHANGED
@@ -44,7 +44,3 @@ export function installShadowRoot(overlaySheet) {
44
44
  export async function ensureShadowRoot(page) {
45
45
  await page.evaluate(installShadowRoot, getOverlaySheet()).catch(() => { });
46
46
  }
47
- /** Also define the helpers on every future document (pilot overlay persists across navigations). */
48
- export async function installShadowRootEverywhere(context) {
49
- await context.addInitScript(installShadowRoot, getOverlaySheet());
50
- }
@@ -18,14 +18,3 @@ export interface Tone {
18
18
  export declare const TONES: Record<ToneName, Tone>;
19
19
  /** Dark surface shared by panels, banner, docks, HUD chips. */
20
20
  export declare const SURFACE = "rgba(20,10,40,.94)";
21
- export declare const ACCENT = "#7C3AED";
22
- /** Secondary accent used on the dark surface (section titles, kinds). */
23
- export declare const ACCENT_SOFT = "#c9a6ff";
24
- /** Stacking order: one scale instead of magic numbers. */
25
- export declare const Z: {
26
- readonly top: 2147483647;
27
- readonly ring: 2147483646;
28
- readonly fx: 2147483645;
29
- readonly focus: 2147483644;
30
- readonly dock: 2147483000;
31
- };
package/dist/ui/tokens.js CHANGED
@@ -14,8 +14,3 @@ export const TONES = {
14
14
  };
15
15
  /** Dark surface shared by panels, banner, docks, HUD chips. */
16
16
  export const SURFACE = "rgba(20,10,40,.94)";
17
- export const ACCENT = "#7C3AED";
18
- /** Secondary accent used on the dark surface (section titles, kinds). */
19
- export const ACCENT_SOFT = "#c9a6ff";
20
- /** Stacking order: one scale instead of magic numbers. */
21
- export const Z = { top: 2147483647, ring: 2147483646, fx: 2147483645, focus: 2147483644, dock: 2147483000 };
@@ -0,0 +1,8 @@
1
+ /** The user's Downloads folder, or undefined when there is none (a server, a container). */
2
+ export declare function downloadsDir(): string | undefined;
3
+ /**
4
+ * Where `--video` recordings go: `WAYGRAPH_VIDEO_DIR`, else `video.dir` from the config (absolute, `~/…`, or relative to
5
+ * the project), else `<Downloads>/waygraph-videos/<project>`. With no usable Downloads folder, or on CI, it is
6
+ * `<project>/.waygraph-videos`. An explicit `--video <dir>` never reaches this.
7
+ */
8
+ export declare function resolveVideoDir(projectDir: string): Promise<string>;
@@ -0,0 +1,60 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { basename, isAbsolute, join, resolve } from "node:path";
4
+ import { loadWaygraphConfig } from "./config.js";
5
+ /** The user's Downloads folder, or undefined when there is none (a server, a container). */
6
+ export function downloadsDir() {
7
+ const home = homedir();
8
+ let dir = process.env.XDG_DOWNLOAD_DIR;
9
+ if (!dir && process.platform === "linux") {
10
+ try {
11
+ const line = readFileSync(join(process.env.XDG_CONFIG_HOME ?? join(home, ".config"), "user-dirs.dirs"), "utf-8")
12
+ .split("\n")
13
+ .find((l) => l.startsWith("XDG_DOWNLOAD_DIR="));
14
+ dir = line?.slice("XDG_DOWNLOAD_DIR=".length).replace(/^"|"$/g, "").replace("$HOME", home);
15
+ }
16
+ catch {
17
+ /* no user-dirs file: use the conventional name */
18
+ }
19
+ }
20
+ dir ??= join(home, "Downloads");
21
+ return existsSync(dir) ? dir : undefined;
22
+ }
23
+ const expandHome = (p) => (p === "~" || p.startsWith("~/") ? join(homedir(), p.slice(1)) : p);
24
+ /** True if a file can be created in `dir` (macOS asks permission for Downloads the first time; a denial surfaces here). */
25
+ function writable(dir) {
26
+ try {
27
+ mkdirSync(dir, { recursive: true });
28
+ const probe = join(dir, `.waygraph-probe-${process.pid}`);
29
+ writeFileSync(probe, "");
30
+ rmSync(probe);
31
+ return true;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ /**
38
+ * Where `--video` recordings go: `WAYGRAPH_VIDEO_DIR`, else `video.dir` from the config (absolute, `~/…`, or relative to
39
+ * the project), else `<Downloads>/waygraph-videos/<project>`. With no usable Downloads folder, or on CI, it is
40
+ * `<project>/.waygraph-videos`. An explicit `--video <dir>` never reaches this.
41
+ */
42
+ export async function resolveVideoDir(projectDir) {
43
+ const fallback = join(projectDir, ".waygraph-videos");
44
+ const configured = process.env.WAYGRAPH_VIDEO_DIR || (await loadWaygraphConfig(projectDir))?.video?.dir;
45
+ if (configured) {
46
+ const dir = isAbsolute(expandHome(configured)) ? expandHome(configured) : resolve(projectDir, configured);
47
+ if (writable(dir))
48
+ return dir;
49
+ console.error(`waygraph: cannot write videos to ${dir} - using ${fallback}`);
50
+ return fallback;
51
+ }
52
+ const downloads = process.env.CI ? undefined : downloadsDir();
53
+ if (!downloads)
54
+ return fallback;
55
+ const dir = join(downloads, "waygraph-videos", basename(resolve(projectDir)));
56
+ if (writable(dir))
57
+ return dir;
58
+ console.error(`waygraph: cannot write to ${downloads} (denied?) - saving videos in ${fallback}`);
59
+ return fallback;
60
+ }
@@ -0,0 +1,14 @@
1
+ /** The subset of Playwright's `TestConfigWebServer` this drives - same field names. */
2
+ export interface WebServerConfig {
3
+ command: string;
4
+ cwd?: string;
5
+ env?: Record<string, string>;
6
+ port?: number;
7
+ url?: string;
8
+ reuseExistingServer?: boolean;
9
+ timeout?: number;
10
+ stdout?: "pipe" | "ignore";
11
+ stderr?: "pipe" | "ignore";
12
+ }
13
+ /** Runs `fn` with the project's `webServer` (if any) up; only servers this call started get stopped. */
14
+ export declare function withWebServer<T>(projectDir: string, fn: () => Promise<T>): Promise<T>;
@@ -0,0 +1,95 @@
1
+ // Starts/stops a project's `webServer` (waygraph.config, or a legacy playwright.config) around `waygraph run`/`demo`/`auto`,
2
+ // the same block `waygraph test` already honors.
3
+ import { existsSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ 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
+ ];
15
+ async function loadWebServerConfigs(projectDir) {
16
+ 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 [];
36
+ }
37
+ async function isUp(target) {
38
+ try {
39
+ return (await fetch(target)).status < 500;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ async function waitUntilUp(target, timeoutMs) {
46
+ const start = Date.now();
47
+ while (Date.now() - start < timeoutMs) {
48
+ if (await isUp(target))
49
+ return;
50
+ await new Promise((r) => setTimeout(r, 100));
51
+ }
52
+ throw new Error(`waygraph: webServer "${target}" not ready after ${timeoutMs}ms`);
53
+ }
54
+ async function startWebServers(configs, projectDir) {
55
+ const started = [];
56
+ for (const cfg of configs) {
57
+ const target = cfg.url ?? (cfg.port ? `http://localhost:${cfg.port}` : undefined);
58
+ if (!target)
59
+ throw new Error(`waygraph: webServer needs "url" or "port"`);
60
+ if (cfg.reuseExistingServer !== false && (await isUp(target)))
61
+ continue;
62
+ // detached = own process group, so stop() kills the shell AND whatever it exec'd.
63
+ const child = spawn(cfg.command, {
64
+ shell: true,
65
+ detached: true,
66
+ cwd: cfg.cwd ? join(projectDir, cfg.cwd) : projectDir,
67
+ env: { ...process.env, ...cfg.env },
68
+ stdio: ["ignore", cfg.stdout === "pipe" ? "inherit" : "ignore", cfg.stderr === "ignore" ? "ignore" : "inherit"],
69
+ });
70
+ started.push(child);
71
+ await waitUntilUp(target, cfg.timeout ?? 60_000);
72
+ }
73
+ return started;
74
+ }
75
+ function stopWebServers(started) {
76
+ for (const child of started) {
77
+ try {
78
+ if (typeof child.pid === "number")
79
+ process.kill(-child.pid, "SIGTERM");
80
+ }
81
+ catch {
82
+ /* already exited */
83
+ }
84
+ }
85
+ }
86
+ /** Runs `fn` with the project's `webServer` (if any) up; only servers this call started get stopped. */
87
+ export async function withWebServer(projectDir, fn) {
88
+ const started = await startWebServers(await loadWebServerConfigs(projectDir), projectDir);
89
+ try {
90
+ return await fn();
91
+ }
92
+ finally {
93
+ stopWebServers(started);
94
+ }
95
+ }
@@ -6,11 +6,11 @@
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": "npm run fixture:test",
9
+ "test": "playwright test",
10
10
  "fixture": "node scripts/fixture-server.mjs",
11
- "fixture:test": "node scripts/with-fixture.mjs npx playwright test",
12
11
  "graph": "waygraph graph",
13
- "auto:cli": "node scripts/with-fixture.mjs waygraph auto --cli"
12
+ "map": "waygraph map",
13
+ "auto:cli": "waygraph auto --cli"
14
14
  },
15
15
  "waygraph": {
16
16
  "baseUrl": "http://127.0.0.1:4277"