waygraph 0.15.46 → 0.15.49

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 (353) hide show
  1. package/dist/analysis/graph.js +2 -2
  2. package/dist/auto-session/session.js +2 -2
  3. package/dist/cli/discover.d.ts +1 -1
  4. package/dist/cli/discover.js +1 -1
  5. package/dist/cli.js +1 -1
  6. package/dist/{agent-dive.js → commands/agent-dive-scaffold.js} +2 -2
  7. package/dist/commands/agent-dive.js +1 -1
  8. package/dist/{engine/core.js → core/block.js} +6 -6
  9. package/dist/core/blocks/api.d.ts +54 -0
  10. package/dist/core/blocks/api.js +75 -0
  11. package/dist/{engine → core}/blocks/effect.d.ts +1 -1
  12. package/dist/{engine → core}/blocks/effect.js +1 -1
  13. package/dist/{engine → core}/blocks/method.d.ts +1 -1
  14. package/dist/{engine → core}/blocks/method.js +1 -1
  15. package/dist/{engine → core}/blocks/nav.js +1 -1
  16. package/dist/{engine → core}/blocks/page.js +1 -1
  17. package/dist/{engine → core}/branch-regression.js +2 -3
  18. package/dist/{engine → core}/compose.js +4 -4
  19. package/dist/{engine/engine-class.d.ts → core/engine.d.ts} +2 -133
  20. package/dist/core/engine.js +50 -0
  21. package/dist/{engine → core}/flow.js +5 -5
  22. package/dist/core/map-builder.d.ts +171 -0
  23. package/dist/{engine/engine-class.js → core/map-builder.js} +82 -98
  24. package/dist/{engine → core}/run-graph.js +4 -6
  25. package/dist/core.d.ts +14 -0
  26. package/dist/core.js +15 -0
  27. package/dist/errors.d.ts +54 -20
  28. package/dist/errors.js +67 -20
  29. package/dist/highlights/run-phase.js +15 -2
  30. package/dist/highlights/stub-ctx.js +16 -0
  31. package/dist/highlights/types.d.ts +38 -0
  32. package/dist/index.d.ts +5 -3
  33. package/dist/index.js +1 -1
  34. package/dist/mem-page.js +2 -2
  35. package/dist/mem-stub.d.ts +1 -1
  36. package/dist/pilot-overlay/fixtures.js +55 -43
  37. package/dist/pilot-overlay/shell.js +23 -10
  38. package/dist/runner/banner-log.js +1 -0
  39. package/dist/runner/device-stage.js +35 -15
  40. package/dist/runner/inpage/banner.d.ts +21 -0
  41. package/dist/runner/inpage/banner.js +29 -4
  42. package/dist/runner/inpage/caption.d.ts +3 -0
  43. package/dist/runner/inpage/caption.js +23 -0
  44. package/dist/runner/inpage/core.js +32 -9
  45. package/dist/runner/inpage/network.d.ts +15 -0
  46. package/dist/runner/inpage/network.js +217 -0
  47. package/dist/runner/inpage/panel-chrome.js +41 -1
  48. package/dist/runner/inpage/swipe-zoom.js +1 -1
  49. package/dist/runner/inpage/todos.js +6 -1
  50. package/dist/runner/main.js +9 -2
  51. package/dist/runner/network-capture.d.ts +9 -0
  52. package/dist/runner/network-capture.js +126 -0
  53. package/dist/runner/overlay-css.js +71 -7
  54. package/dist/runner/overlay-install.js +39 -2
  55. package/dist/runner/overlay-stage.js +5 -0
  56. package/dist/runner/rings.js +69 -45
  57. package/dist/runner/slides.js +14 -8
  58. package/dist/runner/step-mode.js +12 -0
  59. package/dist/runner/step-panels.js +9 -3
  60. package/dist/runner/teardown.js +16 -9
  61. package/dist/session/auto-explore-run.d.ts +1 -1
  62. package/dist/session/auto-explore-run.js +47 -10
  63. package/dist/{step-overlay.d.ts → session/step-overlay.d.ts} +1 -1
  64. package/dist/{step-overlay.js → session/step-overlay.js} +1 -1
  65. package/dist/trait.d.ts +1 -0
  66. package/dist/trait.js +15 -0
  67. package/dist/traverse/run.js +1 -1
  68. package/dist/ui/components/ring.js +4 -2
  69. package/dist/ui/overlay.css +36 -3
  70. package/examples/saucedemo/.waygraph-auto/00d147d1.log +21 -0
  71. package/examples/saucedemo/.waygraph-auto/02f7dd22.log +20 -0
  72. package/examples/saucedemo/.waygraph-auto/0402cfcf.log +6 -0
  73. package/examples/saucedemo/.waygraph-auto/062b581f.log +20 -0
  74. package/examples/saucedemo/.waygraph-auto/0681582b.log +6 -0
  75. package/examples/saucedemo/.waygraph-auto/07f3e964.log +6 -0
  76. package/examples/saucedemo/.waygraph-auto/0868ae4d.log +0 -0
  77. package/examples/saucedemo/.waygraph-auto/0924ddaa.log +22 -0
  78. package/examples/saucedemo/.waygraph-auto/092d6173.log +5 -0
  79. package/examples/saucedemo/.waygraph-auto/09924510.log +0 -0
  80. package/examples/saucedemo/.waygraph-auto/0998c941.log +21 -0
  81. package/examples/saucedemo/.waygraph-auto/0bf74300.log +21 -0
  82. package/examples/saucedemo/.waygraph-auto/0c01fd29.log +4 -0
  83. package/examples/saucedemo/.waygraph-auto/0c302590.log +0 -0
  84. package/examples/saucedemo/.waygraph-auto/0dee62d6.log +5 -0
  85. package/examples/saucedemo/.waygraph-auto/0eb4c081.log +5 -0
  86. package/examples/saucedemo/.waygraph-auto/10fd431c.log +0 -0
  87. package/examples/saucedemo/.waygraph-auto/13c6fe3c.log +0 -0
  88. package/examples/saucedemo/.waygraph-auto/1581b677.log +0 -0
  89. package/examples/saucedemo/.waygraph-auto/164761a5.log +6 -0
  90. package/examples/saucedemo/.waygraph-auto/1905ceb2.log +0 -0
  91. package/examples/saucedemo/.waygraph-auto/1b1d55c6.log +0 -0
  92. package/examples/saucedemo/.waygraph-auto/1b80fd24.log +6 -0
  93. package/examples/saucedemo/.waygraph-auto/1c30a3c2.log +0 -0
  94. package/examples/saucedemo/.waygraph-auto/1c58a174.log +0 -0
  95. package/examples/saucedemo/.waygraph-auto/1d90aa9a.log +0 -0
  96. package/examples/saucedemo/.waygraph-auto/1de7d889.log +0 -0
  97. package/examples/saucedemo/.waygraph-auto/1f233a4c.log +6 -0
  98. package/examples/saucedemo/.waygraph-auto/20e66801.log +0 -0
  99. package/examples/saucedemo/.waygraph-auto/20ffdb77.log +0 -0
  100. package/examples/saucedemo/.waygraph-auto/22f1a704.log +5 -0
  101. package/examples/saucedemo/.waygraph-auto/239cced3.log +20 -0
  102. package/examples/saucedemo/.waygraph-auto/25204b46.log +4 -0
  103. package/examples/saucedemo/.waygraph-auto/25e2e90f.log +0 -0
  104. package/examples/saucedemo/.waygraph-auto/2708455e.log +22 -0
  105. package/examples/saucedemo/.waygraph-auto/272a96fd.log +20 -0
  106. package/examples/saucedemo/.waygraph-auto/28d7be5d.log +0 -0
  107. package/examples/saucedemo/.waygraph-auto/2a6a8266.log +6 -0
  108. package/examples/saucedemo/.waygraph-auto/2b3401cf.log +20 -0
  109. package/examples/saucedemo/.waygraph-auto/2ceccd6d.log +0 -0
  110. package/examples/saucedemo/.waygraph-auto/2f1b0c13.log +6 -0
  111. package/examples/saucedemo/.waygraph-auto/2f8d4073.log +6 -0
  112. package/examples/saucedemo/.waygraph-auto/30739278.log +6 -0
  113. package/examples/saucedemo/.waygraph-auto/31cb2e80.log +0 -0
  114. package/examples/saucedemo/.waygraph-auto/322d63cd.log +0 -0
  115. package/examples/saucedemo/.waygraph-auto/3239aa8a.log +6 -0
  116. package/examples/saucedemo/.waygraph-auto/326d87b7.log +6 -0
  117. package/examples/saucedemo/.waygraph-auto/3351c0b6.log +0 -0
  118. package/examples/saucedemo/.waygraph-auto/33df0770.log +0 -0
  119. package/examples/saucedemo/.waygraph-auto/340d624d.log +0 -0
  120. package/examples/saucedemo/.waygraph-auto/36367ccf.log +0 -0
  121. package/examples/saucedemo/.waygraph-auto/372536a5.log +6 -0
  122. package/examples/saucedemo/.waygraph-auto/3a412f3c.log +0 -0
  123. package/examples/saucedemo/.waygraph-auto/3a859bd7.log +0 -0
  124. package/examples/saucedemo/.waygraph-auto/3cb0add7.log +0 -0
  125. package/examples/saucedemo/.waygraph-auto/3e42f0d8.log +0 -0
  126. package/examples/saucedemo/.waygraph-auto/4144071d.log +0 -0
  127. package/examples/saucedemo/.waygraph-auto/4176a3c6.log +0 -0
  128. package/examples/saucedemo/.waygraph-auto/41d0793d.log +4 -0
  129. package/examples/saucedemo/.waygraph-auto/41e6feae.log +0 -0
  130. package/examples/saucedemo/.waygraph-auto/424b4d5d.log +0 -0
  131. package/examples/saucedemo/.waygraph-auto/43253aba.log +0 -0
  132. package/examples/saucedemo/.waygraph-auto/438c6c53.log +22 -0
  133. package/examples/saucedemo/.waygraph-auto/4477db12.log +0 -0
  134. package/examples/saucedemo/.waygraph-auto/4a1258b7.log +0 -0
  135. package/examples/saucedemo/.waygraph-auto/4adcd179.log +20 -0
  136. package/examples/saucedemo/.waygraph-auto/4c9d9b16.log +21 -0
  137. package/examples/saucedemo/.waygraph-auto/4da39c36.log +6 -0
  138. package/examples/saucedemo/.waygraph-auto/4dbefa7e.log +5 -0
  139. package/examples/saucedemo/.waygraph-auto/4efa7035.log +6 -0
  140. package/examples/saucedemo/.waygraph-auto/505affdc.log +4 -0
  141. package/examples/saucedemo/.waygraph-auto/51bcb60a.log +0 -0
  142. package/examples/saucedemo/.waygraph-auto/5291bc78.log +22 -0
  143. package/examples/saucedemo/.waygraph-auto/54274c39.log +5 -0
  144. package/examples/saucedemo/.waygraph-auto/5440ce7e.log +0 -0
  145. package/examples/saucedemo/.waygraph-auto/5738175f.log +22 -0
  146. package/examples/saucedemo/.waygraph-auto/57ce5643.log +22 -0
  147. package/examples/saucedemo/.waygraph-auto/5984426b.log +6 -0
  148. package/examples/saucedemo/.waygraph-auto/5a682e7c.log +22 -0
  149. package/examples/saucedemo/.waygraph-auto/5b79320c.log +21 -0
  150. package/examples/saucedemo/.waygraph-auto/5c55aaac.log +21 -0
  151. package/examples/saucedemo/.waygraph-auto/5ed00b16.log +4 -0
  152. package/examples/saucedemo/.waygraph-auto/60b9c066.log +6 -0
  153. package/examples/saucedemo/.waygraph-auto/610dd127.log +0 -0
  154. package/examples/saucedemo/.waygraph-auto/61105500.log +5 -0
  155. package/examples/saucedemo/.waygraph-auto/61333142.log +5 -0
  156. package/examples/saucedemo/.waygraph-auto/6134afe8.log +20 -0
  157. package/examples/saucedemo/.waygraph-auto/61937e83.log +22 -0
  158. package/examples/saucedemo/.waygraph-auto/62a0bdc9.log +22 -0
  159. package/examples/saucedemo/.waygraph-auto/6376fc15.log +0 -0
  160. package/examples/saucedemo/.waygraph-auto/6599cbca.log +22 -0
  161. package/examples/saucedemo/.waygraph-auto/67aaca30.log +0 -0
  162. package/examples/saucedemo/.waygraph-auto/68b10298.log +0 -0
  163. package/examples/saucedemo/.waygraph-auto/68be5e12.log +0 -0
  164. package/examples/saucedemo/.waygraph-auto/68df05a6.log +22 -0
  165. package/examples/saucedemo/.waygraph-auto/693f67c4.log +20 -0
  166. package/examples/saucedemo/.waygraph-auto/69ae030a.log +6 -0
  167. package/examples/saucedemo/.waygraph-auto/69e73f35.log +6 -0
  168. package/examples/saucedemo/.waygraph-auto/6b2333b0.log +5 -0
  169. package/examples/saucedemo/.waygraph-auto/6c4c3817.log +0 -0
  170. package/examples/saucedemo/.waygraph-auto/6c954911.log +0 -0
  171. package/examples/saucedemo/.waygraph-auto/6d65a439.log +5 -0
  172. package/examples/saucedemo/.waygraph-auto/6d700055.log +0 -0
  173. package/examples/saucedemo/.waygraph-auto/6ead848f.log +0 -0
  174. package/examples/saucedemo/.waygraph-auto/72675b2d.log +6 -0
  175. package/examples/saucedemo/.waygraph-auto/733dd260.log +5 -0
  176. package/examples/saucedemo/.waygraph-auto/75016486.log +0 -0
  177. package/examples/saucedemo/.waygraph-auto/752b01c6.log +22 -0
  178. package/examples/saucedemo/.waygraph-auto/75675227.log +6 -0
  179. package/examples/saucedemo/.waygraph-auto/75e2e658.log +0 -0
  180. package/examples/saucedemo/.waygraph-auto/76ac1a86.log +0 -0
  181. package/examples/saucedemo/.waygraph-auto/77605295.log +0 -0
  182. package/examples/saucedemo/.waygraph-auto/792671f4.log +22 -0
  183. package/examples/saucedemo/.waygraph-auto/79915adb.log +20 -0
  184. package/examples/saucedemo/.waygraph-auto/7a398774.log +6 -0
  185. package/examples/saucedemo/.waygraph-auto/7a72f66e.log +6 -0
  186. package/examples/saucedemo/.waygraph-auto/7a984334.log +4 -0
  187. package/examples/saucedemo/.waygraph-auto/7c6ee793.log +20 -0
  188. package/examples/saucedemo/.waygraph-auto/7c726dc4.log +22 -0
  189. package/examples/saucedemo/.waygraph-auto/7c72e8a5.log +4 -0
  190. package/examples/saucedemo/.waygraph-auto/7dbee625.log +22 -0
  191. package/examples/saucedemo/.waygraph-auto/7df66956.log +0 -0
  192. package/examples/saucedemo/.waygraph-auto/7e053160.log +0 -0
  193. package/examples/saucedemo/.waygraph-auto/802a0b5b.log +0 -0
  194. package/examples/saucedemo/.waygraph-auto/80322e0b.log +0 -0
  195. package/examples/saucedemo/.waygraph-auto/80a4978e.log +6 -0
  196. package/examples/saucedemo/.waygraph-auto/81cfe480.log +22 -0
  197. package/examples/saucedemo/.waygraph-auto/832f5add.log +0 -0
  198. package/examples/saucedemo/.waygraph-auto/8337b6ad.log +0 -0
  199. package/examples/saucedemo/.waygraph-auto/8493928e.log +0 -0
  200. package/examples/saucedemo/.waygraph-auto/853bde43.log +0 -0
  201. package/examples/saucedemo/.waygraph-auto/86350ea6.log +22 -0
  202. package/examples/saucedemo/.waygraph-auto/86bb598a.log +0 -0
  203. package/examples/saucedemo/.waygraph-auto/86d09876.log +22 -0
  204. package/examples/saucedemo/.waygraph-auto/878ad01b.log +4 -0
  205. package/examples/saucedemo/.waygraph-auto/87c88ba5.log +0 -0
  206. package/examples/saucedemo/.waygraph-auto/87cb80ff.log +0 -0
  207. package/examples/saucedemo/.waygraph-auto/880b2e78.log +6 -0
  208. package/examples/saucedemo/.waygraph-auto/88527936.log +5 -0
  209. package/examples/saucedemo/.waygraph-auto/893023ea.log +5 -0
  210. package/examples/saucedemo/.waygraph-auto/89416718.log +0 -0
  211. package/examples/saucedemo/.waygraph-auto/8996a857.log +6 -0
  212. package/examples/saucedemo/.waygraph-auto/8a64ba0f.log +6 -0
  213. package/examples/saucedemo/.waygraph-auto/8b1cc2aa.log +6 -0
  214. package/examples/saucedemo/.waygraph-auto/8b73d13e.log +6 -0
  215. package/examples/saucedemo/.waygraph-auto/8d960d31.log +1 -0
  216. package/examples/saucedemo/.waygraph-auto/8d9e5cd2.log +21 -0
  217. package/examples/saucedemo/.waygraph-auto/8ec7d260.log +0 -0
  218. package/examples/saucedemo/.waygraph-auto/8ed43279.log +0 -0
  219. package/examples/saucedemo/.waygraph-auto/93acae32.log +5 -0
  220. package/examples/saucedemo/.waygraph-auto/96321a08.log +0 -0
  221. package/examples/saucedemo/.waygraph-auto/9742b6c2.log +6 -0
  222. package/examples/saucedemo/.waygraph-auto/99cc93eb.log +6 -0
  223. package/examples/saucedemo/.waygraph-auto/9cbfbedc.log +0 -0
  224. package/examples/saucedemo/.waygraph-auto/9dc147d2.log +22 -0
  225. package/examples/saucedemo/.waygraph-auto/a215a395.log +22 -0
  226. package/examples/saucedemo/.waygraph-auto/a23b7086.log +4 -0
  227. package/examples/saucedemo/.waygraph-auto/a35bd5ec.log +0 -0
  228. package/examples/saucedemo/.waygraph-auto/a68995e9.log +22 -0
  229. package/examples/saucedemo/.waygraph-auto/a6e4f936.log +22 -0
  230. package/examples/saucedemo/.waygraph-auto/a7da862b.log +0 -0
  231. package/examples/saucedemo/.waygraph-auto/a82e2a48.log +0 -0
  232. package/examples/saucedemo/.waygraph-auto/a952eb91.log +0 -0
  233. package/examples/saucedemo/.waygraph-auto/a9559653.log +5 -0
  234. package/examples/saucedemo/.waygraph-auto/aa478de2.log +0 -0
  235. package/examples/saucedemo/.waygraph-auto/ac350fc7.log +20 -0
  236. package/examples/saucedemo/.waygraph-auto/acc1b63a.log +0 -0
  237. package/examples/saucedemo/.waygraph-auto/ad12d191.log +0 -0
  238. package/examples/saucedemo/.waygraph-auto/ae3a9b06.log +0 -0
  239. package/examples/saucedemo/.waygraph-auto/b04638f4.log +6 -0
  240. package/examples/saucedemo/.waygraph-auto/b48863e5.log +22 -0
  241. package/examples/saucedemo/.waygraph-auto/b56968e1.log +6 -0
  242. package/examples/saucedemo/.waygraph-auto/b64e0620.log +20 -0
  243. package/examples/saucedemo/.waygraph-auto/b86a6218.log +6 -0
  244. package/examples/saucedemo/.waygraph-auto/b8e9e956.log +22 -0
  245. package/examples/saucedemo/.waygraph-auto/b9b310ff.log +21 -0
  246. package/examples/saucedemo/.waygraph-auto/bc111745.log +22 -0
  247. package/examples/saucedemo/.waygraph-auto/bf7a77a2.log +0 -0
  248. package/examples/saucedemo/.waygraph-auto/c0d6f353.log +21 -0
  249. package/examples/saucedemo/.waygraph-auto/c0febcf2.log +20 -0
  250. package/examples/saucedemo/.waygraph-auto/c4c52998.log +6 -0
  251. package/examples/saucedemo/.waygraph-auto/c809ceb4.log +22 -0
  252. package/examples/saucedemo/.waygraph-auto/ca6de7e7.log +0 -0
  253. package/examples/saucedemo/.waygraph-auto/ca8561bc.log +0 -0
  254. package/examples/saucedemo/.waygraph-auto/cb86d45b.log +0 -0
  255. package/examples/saucedemo/.waygraph-auto/cb9a1978.log +6 -0
  256. package/examples/saucedemo/.waygraph-auto/cbbc689c.log +6 -0
  257. package/examples/saucedemo/.waygraph-auto/cd88364b.log +0 -0
  258. package/examples/saucedemo/.waygraph-auto/cd919e1d.log +0 -0
  259. package/examples/saucedemo/.waygraph-auto/cfff9eef.log +20 -0
  260. package/examples/saucedemo/.waygraph-auto/d0f59b21.log +4 -0
  261. package/examples/saucedemo/.waygraph-auto/d1195079.log +20 -0
  262. package/examples/saucedemo/.waygraph-auto/d2ef067a.log +5 -0
  263. package/examples/saucedemo/.waygraph-auto/d425471f.log +6 -0
  264. package/examples/saucedemo/.waygraph-auto/d5293921.log +0 -0
  265. package/examples/saucedemo/.waygraph-auto/d62a22c2.log +21 -0
  266. package/examples/saucedemo/.waygraph-auto/d6d1761f.log +22 -0
  267. package/examples/saucedemo/.waygraph-auto/d6d5f411.log +22 -0
  268. package/examples/saucedemo/.waygraph-auto/d6df2771.log +6 -0
  269. package/examples/saucedemo/.waygraph-auto/d7075012.log +21 -0
  270. package/examples/saucedemo/.waygraph-auto/d9ddc297.log +0 -0
  271. package/examples/saucedemo/.waygraph-auto/db4ac845.log +0 -0
  272. package/examples/saucedemo/.waygraph-auto/db6d7774.log +0 -0
  273. package/examples/saucedemo/.waygraph-auto/db839827.log +5 -0
  274. package/examples/saucedemo/.waygraph-auto/dde5e859.log +22 -0
  275. package/examples/saucedemo/.waygraph-auto/de8cac58.log +0 -0
  276. package/examples/saucedemo/.waygraph-auto/ded5511a.log +6 -0
  277. package/examples/saucedemo/.waygraph-auto/dedfcb18.log +0 -0
  278. package/examples/saucedemo/.waygraph-auto/def4d9b1.log +0 -0
  279. package/examples/saucedemo/.waygraph-auto/e1549e40.log +0 -0
  280. package/examples/saucedemo/.waygraph-auto/e1b0676d.log +21 -0
  281. package/examples/saucedemo/.waygraph-auto/e5111463.log +0 -0
  282. package/examples/saucedemo/.waygraph-auto/e5fc1d7c.log +5 -0
  283. package/examples/saucedemo/.waygraph-auto/e6fd2202.log +0 -0
  284. package/examples/saucedemo/.waygraph-auto/edaa806d.log +0 -0
  285. package/examples/saucedemo/.waygraph-auto/edaf33de.log +0 -0
  286. package/examples/saucedemo/.waygraph-auto/edd40cbb.log +20 -0
  287. package/examples/saucedemo/.waygraph-auto/eddfbffc.log +6 -0
  288. package/examples/saucedemo/.waygraph-auto/ee9fa1ad.log +5 -0
  289. package/examples/saucedemo/.waygraph-auto/ef319474.log +22 -0
  290. package/examples/saucedemo/.waygraph-auto/f28eee8d.log +0 -0
  291. package/examples/saucedemo/.waygraph-auto/f33bde90.log +0 -0
  292. package/examples/saucedemo/.waygraph-auto/f6ba7cb4.log +6 -0
  293. package/examples/saucedemo/.waygraph-auto/f7ac4d62.log +20 -0
  294. package/examples/saucedemo/.waygraph-auto/f929bb79.log +0 -0
  295. package/examples/saucedemo/.waygraph-auto/f92d4c6c.log +22 -0
  296. package/examples/saucedemo/.waygraph-auto/f92faf40.log +5 -0
  297. package/examples/saucedemo/.waygraph-auto/fa784369.log +21 -0
  298. package/examples/saucedemo/.waygraph-auto/fb55f723.log +20 -0
  299. package/examples/saucedemo/.waygraph-auto/fba3b738.log +0 -0
  300. package/examples/saucedemo/.waygraph-auto/ffdf2854.log +6 -0
  301. package/examples/saucedemo/README.md +13 -2
  302. package/examples/saucedemo/package.json +4 -0
  303. package/examples/saucedemo/src/flows/api-demo.flow.ts +37 -0
  304. package/examples/saucedemo/src/flows/checkout.flow.ts +34 -11
  305. package/package.json +5 -3
  306. package/dist/auto-explore-run.d.ts +0 -37
  307. package/dist/auto-explore-run.js +0 -670
  308. package/dist/auto-explore.d.ts +0 -57
  309. package/dist/auto-explore.js +0 -376
  310. package/dist/auto-session-ipc.d.ts +0 -150
  311. package/dist/auto-session-ipc.js +0 -497
  312. package/dist/block-inject.d.ts +0 -15
  313. package/dist/block-inject.js +0 -91
  314. package/dist/browser.d.ts +0 -15
  315. package/dist/browser.js +0 -29
  316. package/dist/coverage-gap.d.ts +0 -11
  317. package/dist/coverage-gap.js +0 -119
  318. package/dist/engine.d.ts +0 -12
  319. package/dist/engine.js +0 -13
  320. package/dist/graph.d.ts +0 -92
  321. package/dist/graph.js +0 -467
  322. package/dist/highlight-shorthand.d.ts +0 -24
  323. package/dist/highlight-shorthand.js +0 -30
  324. package/dist/map-check.d.ts +0 -18
  325. package/dist/map-check.js +0 -140
  326. package/dist/overlay-beacon.d.ts +0 -44
  327. package/dist/overlay-beacon.js +0 -85
  328. package/dist/pilot.d.ts +0 -54
  329. package/dist/pilot.js +0 -80
  330. package/dist/practices-check.d.ts +0 -14
  331. package/dist/practices-check.js +0 -195
  332. package/dist/traverse-coverage.d.ts +0 -59
  333. package/dist/traverse-coverage.js +0 -127
  334. package/dist/traverse-lease.d.ts +0 -18
  335. package/dist/traverse-lease.js +0 -62
  336. package/dist/traverse-run.d.ts +0 -47
  337. package/dist/traverse-run.js +0 -439
  338. package/dist/ui/compose.d.ts +0 -4
  339. package/dist/ui/compose.js +0 -7
  340. /package/dist/{verbose-log.d.ts → auto-session/verbose-log.d.ts} +0 -0
  341. /package/dist/{verbose-log.js → auto-session/verbose-log.js} +0 -0
  342. /package/dist/{agent-dive.d.ts → commands/agent-dive-scaffold.d.ts} +0 -0
  343. /package/dist/{engine/core.d.ts → core/block.d.ts} +0 -0
  344. /package/dist/{engine → core}/blocks/nav.d.ts +0 -0
  345. /package/dist/{engine → core}/blocks/page.d.ts +0 -0
  346. /package/dist/{engine → core}/branch-regression.d.ts +0 -0
  347. /package/dist/{engine → core}/compose.d.ts +0 -0
  348. /package/dist/{engine → core}/config.d.ts +0 -0
  349. /package/dist/{engine → core}/config.js +0 -0
  350. /package/dist/{engine → core}/flow.d.ts +0 -0
  351. /package/dist/{engine → core}/locate.d.ts +0 -0
  352. /package/dist/{engine → core}/locate.js +0 -0
  353. /package/dist/{engine → core}/run-graph.d.ts +0 -0
@@ -97,6 +97,11 @@ export function createOverlayStage(page, { todoDockRef, deviceRef }) {
97
97
  deviceRef.current = state.lastDevice;
98
98
  if (appliedDevice.sync !== "keep" || (reapplyDeviceOnKeep && state.lastDevice)) {
99
99
  await applyDeviceToPage(page, state.lastDevice, appliedDevice.sync);
100
+ // A deliberate settle beat: applyDeviceToPage's own viewport lerp is fully awaited above, but
101
+ // a ring/camera-zoom transition kicked off immediately after (the very next thing this step
102
+ // does) reads as happening AT THE SAME TIME as the device change on video, with no visual
103
+ // breathing room between them - two transitions with no gap look like one confused one.
104
+ await new Promise((r) => setTimeout(r, 220));
100
105
  }
101
106
  return { appliedTodo, appliedDevice };
102
107
  };
@@ -207,15 +207,25 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
207
207
  try {
208
208
  await ensureSelectorInView(page, h.selector);
209
209
  await applyHighlightZoom(page, h.selector, h.zoom, h.zoomOut);
210
- // Prefer live in-page rect (honors device-shell scale) over Playwright box.
211
- const box = await page
212
- .evaluate((sel) => {
213
- const el = document.querySelector(sel);
214
- if (!el) return null;
215
- const r = el.getBoundingClientRect();
216
- return { x: r.x, y: r.y, width: r.width, height: r.height };
217
- }, h.selector)
218
- .catch(() => null);
210
+ // Prefer live in-page rect (honors device-shell scale) over Playwright's own boundingBox() -
211
+ // but resolve the element through Playwright's OWN locator (full selector engine: >>
212
+ // piercing, :has-text(), :visible, ...), not a raw DOM querySelector, which only understands
213
+ // real CSS and silently fails to match any Playwright-specific selector syntax.
214
+ // count() gate: a real, caught regression - Locator.evaluate() has no timeout option and
215
+ // auto-waits (Playwright's default ~30s) for a match to appear, unlike the instant
216
+ // document.querySelector it replaced. count() alone never waits, so this stays an immediate
217
+ // "does it exist right now" check - ensureSelectorInView above already gave the page a real
218
+ // moment to settle.
219
+ const hLoc = page.locator(h.selector).first();
220
+ const box =
221
+ (await hLoc.count().catch(() => 0)) > 0
222
+ ? await hLoc
223
+ .evaluate((el) => {
224
+ const r = el.getBoundingClientRect();
225
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
226
+ })
227
+ .catch(() => null)
228
+ : null;
219
229
  if (box && box.width > 0 && box.height > 0) {
220
230
  await showRing(page, box, h.label, h.tone || "planned", {
221
231
  size: h.size,
@@ -318,44 +328,52 @@ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
318
328
  }
319
329
  if (list.length > 0) {
320
330
  const last = list[list.length - 1];
331
+ // Resolved through Playwright's own locator (>> piercing / :has-text() / :visible support),
332
+ // not handed to the page as a string for a raw DOM querySelector to fail silently on - see
333
+ // showRing's own comment (same fix, same reason) and __wgFollowRing's in core.js.
334
+ const handle = last.selector
335
+ ? await page.locator(last.selector).first().elementHandle({ timeout: 100 }).catch(() => null)
336
+ : null;
321
337
  await page
322
- .evaluate((h) => {
323
- if (!window.__wgFollowRing && !window.__wgPositionRing) return;
324
- if (window.__wgFollowRing) {
325
- window.__wgFollowRing(
326
- h.selector,
327
- h.label,
328
- h.tone || "planned",
329
- { size: h.size || "md", weight: h.weight || "normal" },
330
- !!h.focus,
331
- );
332
- return;
333
- }
334
- const reposition = () => {
335
- const el = document.querySelector(h.selector);
338
+ .evaluate(
339
+ ({ h, el }) => {
340
+ if (el && window.__wgFollowRing) {
341
+ window.__wgFollowRing(
342
+ el,
343
+ h.label,
344
+ h.tone || "planned",
345
+ { size: h.size || "md", weight: h.weight || "normal" },
346
+ !!h.focus,
347
+ );
348
+ return;
349
+ }
350
+ if (!window.__wgPositionRing) return;
336
351
  if (!el) {
337
352
  if (window.__wgHideRing) window.__wgHideRing();
338
353
  return;
339
354
  }
340
- const box = el.getBoundingClientRect();
341
- window.__wgPositionRing(box, h.label, h.tone || "planned", {
342
- size: h.size || "md",
343
- weight: h.weight || "normal",
344
- });
345
- if (h.focus && window.__wgApplyFocus) {
346
- window.__wgApplyFocus({
347
- x: box.x,
348
- y: box.y,
349
- width: box.width,
350
- height: box.height,
355
+ const reposition = () => {
356
+ const box = el.getBoundingClientRect();
357
+ window.__wgPositionRing(box, h.label, h.tone || "planned", {
358
+ size: h.size || "md",
359
+ weight: h.weight || "normal",
351
360
  });
352
- }
353
- };
354
- reposition();
355
- window.__wgRingTrack = reposition;
356
- window.addEventListener("resize", reposition);
357
- window.addEventListener("scroll", reposition, true);
358
- }, last)
361
+ if (h.focus && window.__wgApplyFocus) {
362
+ window.__wgApplyFocus({
363
+ x: box.x,
364
+ y: box.y,
365
+ width: box.width,
366
+ height: box.height,
367
+ });
368
+ }
369
+ };
370
+ reposition();
371
+ window.__wgRingTrack = reposition;
372
+ window.addEventListener("resize", reposition);
373
+ window.addEventListener("scroll", reposition, true);
374
+ },
375
+ { h: last, el: handle },
376
+ )
359
377
  .catch(() => {});
360
378
  } else {
361
379
  await hideRing(page);
@@ -417,11 +435,17 @@ export async function showRing(page, box, label, tone, style) {
417
435
  const weight = normalizeHighlightWeight(style && style.weight);
418
436
  const selector = style && style.selector ? String(style.selector) : "";
419
437
  const focus = !!(style && style.focus);
438
+ // Resolve through Playwright's own locator (full selector engine), not a selector string handed
439
+ // to the page for a raw DOM lookup - >> piercing / :has-text() / :visible are Playwright-only
440
+ // syntax, invisible to document.querySelector. The resolved element handle is passed straight
441
+ // into evaluate (Playwright unwraps it to the real DOM node inside the page), so __wgFollowRing's
442
+ // per-frame RAF loop tracks that exact element directly - no repeated selector re-resolution.
443
+ const handle = selector ? await page.locator(selector).first().elementHandle({ timeout: 100 }).catch(() => null) : null;
420
444
  await page
421
445
  .evaluate(
422
- ({ box, label, tone, size, weight, selector, focus }) => {
423
- if (selector && window.__wgFollowRing) {
424
- window.__wgFollowRing(selector, label, tone || "planned", { size, weight }, focus);
446
+ ({ box, label, tone, size, weight, el, focus }) => {
447
+ if (el && window.__wgFollowRing) {
448
+ window.__wgFollowRing(el, label, tone || "planned", { size, weight }, focus);
425
449
  return;
426
450
  }
427
451
  if (window.__wgStopRingFollow) window.__wgStopRingFollow();
@@ -431,7 +455,7 @@ export async function showRing(page, box, label, tone, style) {
431
455
  if (focus && box && window.__wgApplyFocus) window.__wgApplyFocus(box);
432
456
  else if (!focus && window.__wgClearFocus) window.__wgClearFocus();
433
457
  },
434
- { box, label, tone: tone || "planned", size, weight, selector, focus },
458
+ { box, label, tone: tone || "planned", size, weight, el: handle, focus },
435
459
  )
436
460
  .catch(() => {});
437
461
  }
@@ -43,14 +43,20 @@ export async function presentSlides(page, slides, _gate, opts) {
43
43
  try {
44
44
  await ensureSelectorInView(page, s.selector);
45
45
  await applyHighlightZoom(page, s.selector, s.zoom, s.zoomOut);
46
- const box = await page
47
- .evaluate((sel) => {
48
- const el = document.querySelector(sel);
49
- if (!el) return null;
50
- const r = el.getBoundingClientRect();
51
- return { x: r.x, y: r.y, width: r.width, height: r.height };
52
- }, s.selector)
53
- .catch(() => null);
46
+ // Playwright's own locator (>> piercing / :has-text() / :visible support), not a raw
47
+ // querySelector string - see rings.js's showRing for the same fix, same reason. count()
48
+ // gate: Locator.evaluate() has no timeout option and auto-waits ~30s for a match to
49
+ // appear - count() never waits, keeping this an immediate "does it exist now" check.
50
+ const sLoc = page.locator(s.selector).first();
51
+ const box =
52
+ (await sLoc.count().catch(() => 0)) > 0
53
+ ? await sLoc
54
+ .evaluate((el) => {
55
+ const r = el.getBoundingClientRect();
56
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
57
+ })
58
+ .catch(() => null)
59
+ : null;
54
60
  if (box && box.width > 0 && box.height > 0) {
55
61
  await showRing(page, box, caption, slideTone, {
56
62
  ...slideStyle,
@@ -342,6 +342,10 @@ export async function runStepMode(engine, start, end, context, page, mem, resolv
342
342
  justEnteredEpisode,
343
343
  title: overlayTitle,
344
344
  bannerUi: stage.state.lastBannerUi,
345
+ caption: stubBeforePhase.caption,
346
+ networkTabVisible: stubBeforePhase.networkTabVisible,
347
+ fastForward: !!r.block.fastForward,
348
+ isApi: r.block.__waygraphKind === "api",
345
349
  todoPos: overlayTodoPos,
346
350
  episodeNumber: r.episodeNumber,
347
351
  episodeTitle: r.episodeTitle,
@@ -544,6 +548,8 @@ export async function runStepMode(engine, start, end, context, page, mem, resolv
544
548
  let highlights;
545
549
  let stubAfterTodos = [];
546
550
  let afterOverlayTitle = overlayTitle;
551
+ let afterCaption; // undefined = leave whatever's currently shown alone (see installOverlay's own comment)
552
+ let afterNetworkTabVisible; // undefined = leave the network tab's current shown/hidden state alone
547
553
  let afterTodoPos = overlayTodoPos;
548
554
  let appliedAfter = { dock: stage.state.lastTodoDock, sync: "keep" };
549
555
  let appliedDeviceAfter = { device: stage.state.lastDevice, sync: "keep" };
@@ -573,6 +579,8 @@ export async function runStepMode(engine, start, end, context, page, mem, resolv
573
579
  if (afterPhase.title && String(afterPhase.title).trim()) {
574
580
  afterOverlayTitle = String(afterPhase.title).trim();
575
581
  }
582
+ if (afterPhase.caption !== undefined) afterCaption = afterPhase.caption;
583
+ if (afterPhase.networkTabVisible !== undefined) afterNetworkTabVisible = afterPhase.networkTabVisible;
576
584
  if (afterPhase.todoPos) afterTodoPos = afterPhase.todoPos;
577
585
  if (stage.state.lastTodoDock && stage.state.lastTodoDock.pos) afterTodoPos = stage.state.lastTodoDock.pos;
578
586
  highlights = afterPhase.highlights.map((h) => {
@@ -615,6 +623,10 @@ export async function runStepMode(engine, start, end, context, page, mem, resolv
615
623
  allEpisodes,
616
624
  title: afterOverlayTitle,
617
625
  bannerUi: stage.state.lastBannerUi,
626
+ caption: afterCaption,
627
+ networkTabVisible: afterNetworkTabVisible,
628
+ fastForward: !!r.block.fastForward,
629
+ isApi: r.block.__waygraphKind === "api",
618
630
  todoPos: afterTodoPos,
619
631
  episodeNumber: r.episodeNumber,
620
632
  episodeTitle: r.episodeTitle,
@@ -6,7 +6,7 @@ import { applyHighlightStyleDefaults, formatHighlightCaption, hasAuthoredStubOnE
6
6
  import { cycleHighlightRings } from "./rings.js";
7
7
 
8
8
  export async function renderBeforeStep(page, info) {
9
- await installOverlay(page, info.title, info.bannerUi);
9
+ await installOverlay(page, info.title, info.bannerUi, info.caption, info.networkTabVisible);
10
10
  // A ring left highlighting the PREVIOUS step's element (and its live
11
11
  // resize/scroll tracker) shouldn't linger once a new step's own panel is
12
12
  // up - only relevant when a Block's act() doesn't navigate away, since a
@@ -135,6 +135,8 @@ export async function renderBeforeStep(page, info) {
135
135
  window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
136
136
  stepLabel: info.stepLabel || "",
137
137
  forceCollapsed: info.forceCollapsed === true ? true : undefined,
138
+ fastForward: !!info.fastForward,
139
+ isApi: !!info.isApi,
138
140
  });
139
141
  }
140
142
  if (window.__wgSyncTodos) {
@@ -375,7 +377,7 @@ export async function presentFailPanel(page, opts) {
375
377
 
376
378
 
377
379
  export async function renderAfterStep(page, info) {
378
- await installOverlay(page, info.title, info.bannerUi);
380
+ await installOverlay(page, info.title, info.bannerUi, info.caption, info.networkTabVisible);
379
381
  // Clear any tracker from a previous highlight before cycling through this
380
382
  // step's own.
381
383
  await page
@@ -506,6 +508,8 @@ export async function renderAfterStep(page, info) {
506
508
  window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
507
509
  stepLabel: info.stepLabel || "",
508
510
  forceCollapsed: info.forceCollapsed === true ? true : undefined,
511
+ fastForward: !!info.fastForward,
512
+ isApi: !!info.isApi,
509
513
  });
510
514
  }
511
515
  if (window.__wgSyncTodos) {
@@ -574,7 +578,7 @@ export async function renderAfterStep(page, info) {
574
578
  * regardless - main()'s own try/finally - but not before this is visible).
575
579
  */
576
580
  async function renderStepError(page, info) {
577
- await installOverlay(page, info.title, info.bannerUi);
581
+ await installOverlay(page, info.title, info.bannerUi, info.caption, info.networkTabVisible);
578
582
  const errorPayload = { ...info, stepLabel: miniStepLabel(info) };
579
583
  await page
580
584
  .evaluate((info) => {
@@ -640,6 +644,8 @@ async function renderStepError(page, info) {
640
644
  window.__wgWirePanelChrome(panel, "wg-panel-hidden", "waygraph demo", {
641
645
  stepLabel: info.stepLabel || "",
642
646
  forceCollapsed: info.forceCollapsed === true ? true : undefined,
647
+ fastForward: !!info.fastForward,
648
+ isApi: !!info.isApi,
643
649
  });
644
650
  }
645
651
  if (window.__wgStampModal) {
@@ -110,15 +110,22 @@ export async function restoreTheaterAfterNavigation(page, todoDockRef, deviceRef
110
110
  const stubs = (stubBeforeRef && stubBeforeRef.current) || [];
111
111
  for (const h of stubs) {
112
112
  if (!h || !h.selector) continue;
113
- const box = await page
114
- .evaluate((sel) => {
115
- const el = document.querySelector(sel);
116
- if (!el) return null;
117
- const r = el.getBoundingClientRect();
118
- if (r.width < 2 || r.height < 2) return null;
119
- return { x: r.x, y: r.y, width: r.width, height: r.height };
120
- }, h.selector)
121
- .catch(() => null);
113
+ // Playwright's own locator (>> piercing / :has-text() / :visible support), not a raw
114
+ // querySelector string - see rings.js's showRing for the same fix, same reason. count() gate:
115
+ // Locator.evaluate() has no timeout option and auto-waits ~30s for a match to appear - count()
116
+ // never waits, keeping this an immediate "does it still exist" check (this selector routinely
117
+ // won't, after a route change - that's the whole point of the loop).
118
+ const hLoc = page.locator(h.selector).first();
119
+ const box =
120
+ (await hLoc.count().catch(() => 0)) > 0
121
+ ? await hLoc
122
+ .evaluate((el) => {
123
+ const r = el.getBoundingClientRect();
124
+ if (r.width < 2 || r.height < 2) return null;
125
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
126
+ })
127
+ .catch(() => null)
128
+ : null;
122
129
  if (box) {
123
130
  await showRing(page, box, formatHighlightCaption(h), h.tone || "planned", {
124
131
  size: h.size,
@@ -1,5 +1,5 @@
1
1
  import type { Page, BrowserContext } from "@playwright/test";
2
- import { Engine } from "../engine.js";
2
+ import { Engine } from "../core.js";
3
3
  import { MemPage } from "../mem-page.js";
4
4
  import { type BlockEntry } from "./auto-explore.js";
5
5
  import type { Checkpoint } from "../types.js";
@@ -3,10 +3,10 @@ import { ensureShadowRoot } from "../ui/shadow.js";
3
3
  import { stdin as input, stdout as output } from "node:process";
4
4
  import { existsSync, readFileSync } from "node:fs";
5
5
  import { join } from "node:path";
6
- import { Engine, start, end, locate } from "../engine.js";
6
+ import { Engine, start, end, locate } from "../core.js";
7
7
  import { MemPage } from "../mem-page.js";
8
8
  import { buildExploreContext, buildExploreMenu, } from "./auto-explore.js";
9
- import { installDemoChrome, instrumentInteractionHighlighting } from "../step-overlay.js";
9
+ import { installDemoChrome, instrumentInteractionHighlighting } from "./step-overlay.js";
10
10
  export function resolveBaseUrl(projectDir) {
11
11
  const pkgPath = join(projectDir, "package.json");
12
12
  if (existsSync(pkgPath)) {
@@ -355,6 +355,37 @@ async function headfulPick(page, menu, library, mem, waitPick) {
355
355
  memIdx++;
356
356
  }
357
357
  }
358
+ // Pre-resolve every candidate's hover-preview box THROUGH Playwright's own locator (>>
359
+ // piercing / :has-text() / :visible support), once, here on the Node side - not a raw selector
360
+ // string handed to the page for a per-mouseenter document.querySelector to fail silently on
361
+ // (same class of bug as rings.js's showRing; see its own comment for the full story). A
362
+ // mouseenter handler can't itself await a Node-side locator without visible hover lag, so the
363
+ // box is embedded as a data attribute instead and the in-page handler just reads it.
364
+ const hlSelectors = new Set();
365
+ for (const section of menu.sections) {
366
+ for (const c of section.edges) {
367
+ const entry = library.get(c.block);
368
+ const navClick = entry?.block?.__waygraphNavClick;
369
+ const hl = c.instanceOption?.highlight ?? (typeof navClick === "string" ? navClick : undefined);
370
+ if (hl)
371
+ hlSelectors.add(hl);
372
+ }
373
+ }
374
+ const hlBoxes = new Map();
375
+ await Promise.all([...hlSelectors].map(async (sel) => {
376
+ const loc = page.locator(sel).first();
377
+ const box = (await loc.count().catch(() => 0)) > 0
378
+ ? await loc
379
+ .evaluate((el) => {
380
+ const r = el.getBoundingClientRect();
381
+ if (r.width < 1 && r.height < 1)
382
+ return null;
383
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
384
+ })
385
+ .catch(() => null)
386
+ : null;
387
+ hlBoxes.set(sel, box);
388
+ }));
358
389
  html += `<div class="wg-actions">`;
359
390
  let idx = 0;
360
391
  if (menu.sections.length === 0) {
@@ -366,7 +397,8 @@ async function headfulPick(page, menu, library, mem, waitPick) {
366
397
  const entry = library.get(c.block);
367
398
  const navClick = entry?.block?.__waygraphNavClick;
368
399
  const hl = c.instanceOption?.highlight ?? (typeof navClick === "string" ? navClick : undefined);
369
- const hlAttr = hl ? ` data-hl="${esc(hl)}"` : "";
400
+ const hlBox = hl ? hlBoxes.get(hl) : null;
401
+ const hlAttr = hlBox ? ` data-hl-box='${esc(JSON.stringify(hlBox))}'` : "";
370
402
  if (c.label) {
371
403
  html += `<button class="wg-act" data-idx="${idx}"${hlAttr}>${esc(c.label)}</button>`;
372
404
  }
@@ -476,14 +508,19 @@ async function headfulPick(page, menu, library, mem, waitPick) {
476
508
  window.__wgAutoPick?.(idx);
477
509
  });
478
510
  btn.addEventListener("mouseenter", () => {
479
- const sel = btn.getAttribute("data-hl");
480
- if (!sel) return;
481
- const el = document.querySelector(sel);
482
- if (!el || typeof window.__wgPositionRing !== "function") return;
483
- const r = el.getBoundingClientRect();
484
- if (r.width < 1 && r.height < 1) return;
511
+ // Pre-resolved on the Node side via Playwright's own locator (>> piercing / :has-text()
512
+ // support) when this menu was built - see headfulPick's own comment for why a
513
+ // mouseenter handler can't itself round-trip to a Node-side locator per hover.
514
+ const raw = btn.getAttribute("data-hl-box");
515
+ if (!raw || typeof window.__wgPositionRing !== "function") return;
516
+ let box;
517
+ try {
518
+ box = JSON.parse(raw);
519
+ } catch {
520
+ return;
521
+ }
485
522
  window.__wgPositionRing(
486
- { x: r.x, y: r.y, width: r.width, height: r.height },
523
+ box,
487
524
  btn.textContent?.trim()?.slice(0, 80) || "target",
488
525
  "auto",
489
526
  );
@@ -1,5 +1,5 @@
1
1
  import type { Page } from "@playwright/test";
2
- import type { MemPage } from "./mem-page.js";
2
+ import type { MemPage } from "../mem-page.js";
3
3
  export declare function installDemoChrome(page: Page, title?: string, options?: {
4
4
  banner?: boolean;
5
5
  }): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { ensureShadowRoot } from "./ui/shadow.js";
1
+ import { ensureShadowRoot } from "../ui/shadow.js";
2
2
  const FAVICON = "data:image/svg+xml," +
3
3
  encodeURIComponent("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><circle cx='16' cy='16' r='14' fill='#7C3AED'/></svg>");
4
4
  export async function installDemoChrome(page, title = "waygraph auto", options = {}) {
package/dist/trait.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Page } from "@playwright/test";
2
2
  import type { MemPage } from "./mem-page.js";
3
+ import "urlpattern-polyfill";
3
4
  /**
4
5
  * A named, independently-reportable check. `check` never runs before `resolve` has
5
6
  * already decided the Checkpoint, and it can only confirm or fail loud - it has no
package/dist/trait.js CHANGED
@@ -1,3 +1,12 @@
1
+ // URLPattern is only a Node global from v23.8+ (and even then, Node's own, not a browser's) -
2
+ // CI's Node 20/22 matrix has no global at all. Side-effect import only: the polyfill package sets
3
+ // globalThis.URLPattern itself, but only when one doesn't already exist - so below Node 23.8 this
4
+ // becomes THE global, and from 23.8 up it's a no-op and the native one stays. Playwright's own
5
+ // waitForURL(pattern) checks `pattern instanceof globalThis.URLPattern` internally, so the instance
6
+ // constructed below must always come from whatever ends up on globalThis, not this import
7
+ // directly - a named `import { URLPattern }` gives a fixed class that's a different constructor
8
+ // than the native global on newer Node, and `instanceof` would then fail on those versions.
9
+ import "urlpattern-polyfill";
1
10
  /**
2
11
  * Common, generic Trait factories - reusable across any Block, not one-off
3
12
  * `{ name, check }` objects written inline per Block. Reach for one of these
@@ -36,6 +45,12 @@ export function urlMatches(pattern) {
36
45
  // `verify()` case this was originally written for - just via the same
37
46
  // mechanism every other Trait already uses instead of its own
38
47
  // hardcoded, wrong-context value.
48
+ // Cast, not a bare `urlPattern` reference: @types/node and the polyfill both declare an
49
+ // ambient global `URLPattern` (`skipLibCheck` hides the conflict between them instead of
50
+ // erroring), and they resolve to two DIFFERENT types depending on where in the program the
51
+ // name is looked up - so the very same runtime value that satisfies Playwright's actual
52
+ // (structural, .test()-based) check at runtime fails typechecking as "not assignable" against
53
+ // whichever of the two ambient declarations Playwright's own .d.ts happens to see.
39
54
  await page.waitForURL(urlPattern);
40
55
  return true;
41
56
  },
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { readFileSync, existsSync } from "node:fs";
6
6
  import { join } from "node:path";
7
- import { Engine, start, end, locate } from "../engine.js";
7
+ import { Engine, start, end, locate } from "../core.js";
8
8
  import { MemPage } from "../mem-page.js";
9
9
  import { buildExploreContext, buildExploreMenu, } from "../session/auto-explore.js";
10
10
  import { defaultMemValueForKey } from "../session/auto-explore-run.js";
@@ -1,6 +1,8 @@
1
1
  import { TONES } from "../tokens.js";
2
- /** Prefix icon for gray (auto) labels. */
3
- const ROBOT = 'content:"\\1F916\\00a0";';
2
+ /** Prefix icon for gray (auto) labels - a real inline SVG (terminal chevron), not an emoji. */
3
+ const ROBOT = 'content:"";display:inline-block;width:12px;height:12px;margin-right:5px;vertical-align:-1px;' +
4
+ "background-repeat:no-repeat;background-size:contain;" +
5
+ "background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M2.5 3.5l5 4.5-5 4.5M8.5 12.5h5' stroke='white' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");";
4
6
  const toneNames = Object.keys(TONES);
5
7
  /** Tone rules for `sel[data-tone=x]{...}` from the token table. */
6
8
  function toneRules(sel, decl, only) {
@@ -93,8 +93,14 @@
93
93
  .wg-ring-el-label[data-tone=danger] { --wg-tone-bg: var(--wg-tone-danger-bg); --wg-tone-fg: var(--wg-tone-danger-fg); }
94
94
  .wg-ring-el-label[data-tone=success] { --wg-tone-bg: var(--wg-tone-success-bg); --wg-tone-fg: var(--wg-tone-success-fg); }
95
95
  .wg-ring-el-label[data-tone=orange] { --wg-tone-bg: var(--wg-tone-orange-bg); --wg-tone-fg: var(--wg-tone-orange-fg); }
96
- /* Gray (auto) = a real Playwright-driven instruction - mark it, a human/AI watching can't "see" DOM state otherwise. */
97
- .wg-ring-el-label[data-tone=auto]::before { content: "\1F916\00a0"; }
96
+ /* Gray (auto) = a real Playwright-driven instruction - mark it, a human/AI watching can't "see" DOM
97
+ state otherwise. A real inline SVG icon (small terminal chevron), not an emoji - emoji rendering
98
+ is font/OS-dependent and reads as an unpolished placeholder next to the rest of this design. */
99
+ .wg-ring-el-label[data-tone=auto]::before {
100
+ content: ""; display: inline-block; width: 12px; height: 12px; margin-right: 5px;
101
+ vertical-align: -1px; background-repeat: no-repeat; background-size: contain;
102
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M2.5 3.5l5 4.5-5 4.5M8.5 12.5h5' stroke='white' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
103
+ }
98
104
  .wg-ring-el-label[data-size=sm] { font-size: 10px; line-height: 1.25; padding: 4px 7px; border-radius: 5px; }
99
105
  .wg-ring-el-label[data-size=lg] { font-size: 16px; line-height: 1.35; padding: 8px 14px; border-radius: 9px; max-width: min(480px, 85vw); }
100
106
  .wg-ring-el-label[data-weight=bold] { font-weight: 800; }
@@ -136,6 +142,9 @@
136
142
  #wg-banner[data-pos=left] { left: 14px; right: auto; transform: none; }
137
143
  #wg-banner[data-pos=center] { left: 50%; right: auto; transform: translateX(-50%); }
138
144
  #wg-banner[data-pos=right] { right: 14px; left: auto; transform: none; }
145
+ /* Same "auto opacity" step-back the todo dock already has (.wg-todo-behind) while a ring caption
146
+ is the current focus - added via __wgBannerSetBehind, not just the collision-driven move. */
147
+ #wg-banner.wg-banner-behind { opacity: .42; }
139
148
  #wg-banner .wg-banner-tag {
140
149
  display: block; font-size: 10px; font-weight: 700; color: var(--wg-accent-soft);
141
150
  letter-spacing: .05em; text-transform: uppercase; margin-bottom: 2px;
@@ -151,7 +160,7 @@
151
160
  * duplicate of this file's own rules, is consolidated.
152
161
  */
153
162
  #wg-pilot-fx-todos {
154
- position: fixed; z-index: var(--wg-z-fx); top: 72px; max-width: 280px; max-height: calc(100vh - 100px);
163
+ position: fixed; z-index: var(--wg-z-fx); top: 104px; max-width: 280px; max-height: calc(100vh - 132px);
155
164
  overflow: auto; font: 12px/1.4 ui-sans-serif, system-ui, sans-serif; color: #fff;
156
165
  background: var(--wg-surface); border-radius: var(--wg-radius-md); padding: 10px 12px;
157
166
  box-shadow: var(--wg-shadow-dock); pointer-events: auto; transition: opacity .25s ease;
@@ -181,3 +190,27 @@
181
190
  background: var(--wg-surface); color: #fff; border-radius: var(--wg-radius-sm);
182
191
  box-shadow: 0 2px 8px rgba(0,0,0,.25);
183
192
  }
193
+
194
+
195
+ /*
196
+ * Bottom subtitle caption (#wg-caption-bar) - a white rounded card, not a full-width dark scrim
197
+ * (matches the rest of the overlay's light "toast" surfaces - banner/panel are the dark violet
198
+ * chrome, this narrates the PAGE itself so it reads as a caption card, not more chrome).
199
+ */
200
+ #wg-caption-bar {
201
+ position: fixed; z-index: var(--wg-z-focus); left: 0; right: 0; bottom: 0;
202
+ /* Bottom padding clears the collapsed step-pill (#wg-panel, bottom:12px, ~40px tall,
203
+ z-index:2147483647 - always on top) - without it the pill sat right over the caption card,
204
+ both centered at the bottom of the viewport (see #wg-typing-badge's own bottom:88px, same
205
+ reason). */
206
+ padding: 0 6% 64px; display: flex; justify-content: center;
207
+ pointer-events: none; opacity: 0; transform: translateY(6px);
208
+ transition: opacity .3s ease, transform .3s ease;
209
+ }
210
+ #wg-caption-bar.wg-in { opacity: 1; transform: translateY(0); }
211
+ #wg-caption-bar .wg-caption-text {
212
+ font: 500 15px/1.4 var(--wg-font); color: #1c1917; text-align: center;
213
+ max-width: 82%; text-wrap: balance;
214
+ background: #fff; border-radius: var(--wg-radius-lg);
215
+ padding: 10px 18px; box-shadow: var(--wg-shadow-banner);
216
+ }
@@ -0,0 +1,21 @@
1
+ [18:43:31.014] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [18:43:31.014] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [18:43:31.015] waygraph pilot: stub.before ctx.device(mobile)
4
+ [18:43:31.015] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [18:43:31.015] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [18:43:31.780] waygraph pilot: stub.after ctx.todos n=6 index=1
7
+ [18:43:32.878] waygraph pilot: stub.before ring #password tone=planned label="Password"
8
+ [18:43:33.035] waygraph pilot: stub.after ctx.todos n=6 index=2
9
+ [18:43:34.170] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
10
+ [18:43:34.393] waygraph pilot: stub.after ctx.title("Inventory · landscape")
11
+ [18:43:34.393] waygraph pilot: stub.after ctx.todos n=6 index=3
12
+ [18:43:34.393] waygraph pilot: stub.after ctx.device(mobile)
13
+ [18:43:34.393] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
14
+ [18:43:37.076] waygraph pilot: stub.before ctx.title("Open cart · landscape")
15
+ [18:43:37.076] waygraph pilot: stub.before ctx.todos n=6 index=5
16
+ [18:43:37.076] waygraph pilot: stub.before ctx.device(mobile)
17
+ [18:43:37.076] waygraph pilot: stub.before ctx.zoom(1.4)
18
+ [18:43:37.076] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
19
+ [18:43:37.510] waygraph pilot: stub.after ctx.title("Your cart · desktop")
20
+ [18:43:37.511] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"
21
+ [18:43:37.589] waygraph pilot: ring not painted - selector matched nothing (or a zero-size element): .cart_item
@@ -0,0 +1,20 @@
1
+ [13:39:10.711] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [13:39:10.717] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [13:39:10.719] waygraph pilot: stub.before ctx.device(mobile)
4
+ [13:39:10.719] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [13:39:10.719] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [13:39:11.863] waygraph pilot: stub.after ctx.todos n=6 index=1
7
+ [13:39:13.470] waygraph pilot: stub.before ring #password tone=planned label="Password"
8
+ [13:39:13.668] waygraph pilot: stub.after ctx.todos n=6 index=2
9
+ [13:39:15.550] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
10
+ [13:39:15.936] waygraph pilot: stub.after ctx.title("Inventory · landscape")
11
+ [13:39:15.936] waygraph pilot: stub.after ctx.todos n=6 index=3
12
+ [13:39:15.936] waygraph pilot: stub.after ctx.device(mobile)
13
+ [13:39:15.936] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
14
+ [13:39:20.251] waygraph pilot: stub.before ctx.title("Open cart · landscape")
15
+ [13:39:20.252] waygraph pilot: stub.before ctx.todos n=6 index=5
16
+ [13:39:20.252] waygraph pilot: stub.before ctx.device(mobile)
17
+ [13:39:20.252] waygraph pilot: stub.before ctx.zoom(1.4)
18
+ [13:39:20.252] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
19
+ [13:39:20.880] waygraph pilot: stub.after ctx.title("Your cart · desktop")
20
+ [13:39:20.880] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"
@@ -0,0 +1,6 @@
1
+ [14:01:13.381] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [14:01:13.382] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [14:01:13.382] waygraph pilot: stub.before ctx.device(mobile)
4
+ [14:01:13.382] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [14:01:13.382] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [14:01:14.418] waygraph pilot: stub.after ctx.todos n=6 index=1
@@ -0,0 +1,20 @@
1
+ [15:11:57.159] waygraph pilot: stub.before ctx.title("Signing in · mobile")
2
+ [15:11:57.159] waygraph pilot: stub.before ctx.todos n=6 index=0
3
+ [15:11:57.160] waygraph pilot: stub.before ctx.device(mobile)
4
+ [15:11:57.160] waygraph pilot: stub.before ctx.zoom(1.35)
5
+ [15:11:57.160] waygraph pilot: stub.before ring #user-name tone=info label="Username"
6
+ [15:11:58.387] waygraph pilot: stub.after ctx.todos n=6 index=1
7
+ [15:11:59.771] waygraph pilot: stub.before ring #password tone=planned label="Password"
8
+ [15:11:59.868] waygraph pilot: stub.after ctx.todos n=6 index=2
9
+ [15:12:01.498] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
10
+ [15:12:01.761] waygraph pilot: stub.after ctx.title("Inventory · landscape")
11
+ [15:12:01.763] waygraph pilot: stub.after ctx.todos n=6 index=3
12
+ [15:12:01.763] waygraph pilot: stub.after ctx.device(mobile)
13
+ [15:12:01.763] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
14
+ [15:12:05.024] waygraph pilot: stub.before ctx.title("Open cart · landscape")
15
+ [15:12:05.024] waygraph pilot: stub.before ctx.todos n=6 index=5
16
+ [15:12:05.024] waygraph pilot: stub.before ctx.device(mobile)
17
+ [15:12:05.024] waygraph pilot: stub.before ctx.zoom(1.4)
18
+ [15:12:05.024] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
19
+ [15:12:05.374] waygraph pilot: stub.after ctx.title("Your cart · desktop")
20
+ [15:12:05.374] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"