waygraph 0.15.47 → 0.15.50

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 (364) hide show
  1. package/dist/analysis/graph.js +2 -2
  2. package/dist/auto-session/session.js +3 -3
  3. package/dist/cli/discover.d.ts +1 -1
  4. package/dist/cli/discover.js +1 -1
  5. package/dist/cli/flags.d.ts +7 -5
  6. package/dist/cli/flags.js +9 -32
  7. package/dist/cli/run-chain.js +1 -1
  8. package/dist/cli.js +1 -1
  9. package/dist/{agent-dive.js → commands/agent-dive-scaffold.js} +2 -2
  10. package/dist/commands/agent-dive.js +1 -1
  11. package/dist/commands/check.js +1 -1
  12. package/dist/commands/run.js +4 -4
  13. package/dist/commands/session.js +7 -7
  14. package/dist/config.d.ts +34 -0
  15. package/dist/config.js +94 -0
  16. package/dist/{engine/core.js → core/block.js} +6 -6
  17. package/dist/core/blocks/api.d.ts +54 -0
  18. package/dist/core/blocks/api.js +75 -0
  19. package/dist/{engine → core}/blocks/effect.d.ts +1 -1
  20. package/dist/{engine → core}/blocks/effect.js +1 -1
  21. package/dist/{engine → core}/blocks/method.d.ts +1 -1
  22. package/dist/{engine → core}/blocks/method.js +1 -1
  23. package/dist/{engine → core}/blocks/nav.js +1 -1
  24. package/dist/{engine → core}/blocks/page.js +1 -1
  25. package/dist/{engine → core}/branch-regression.js +2 -3
  26. package/dist/{engine → core}/compose.js +4 -4
  27. package/dist/{engine/engine-class.d.ts → core/engine.d.ts} +2 -133
  28. package/dist/core/engine.js +50 -0
  29. package/dist/{engine → core}/flow.js +5 -5
  30. package/dist/core/map-builder.d.ts +171 -0
  31. package/dist/{engine/engine-class.js → core/map-builder.js} +82 -98
  32. package/dist/{engine → core}/run-graph.js +4 -6
  33. package/dist/core.d.ts +14 -0
  34. package/dist/core.js +15 -0
  35. package/dist/env-file.d.ts +10 -0
  36. package/dist/env-file.js +58 -0
  37. package/dist/errors.d.ts +54 -20
  38. package/dist/errors.js +67 -20
  39. package/dist/highlights/run-phase.js +15 -2
  40. package/dist/highlights/stub-ctx.js +16 -0
  41. package/dist/highlights/types.d.ts +38 -0
  42. package/dist/index.d.ts +7 -3
  43. package/dist/index.js +2 -1
  44. package/dist/mem-page.js +2 -2
  45. package/dist/mem-stub.d.ts +1 -1
  46. package/dist/pilot-overlay/fixtures.js +42 -10
  47. package/dist/pilot-overlay/shell.js +23 -10
  48. package/dist/runner/banner-log.js +1 -0
  49. package/dist/runner/device-stage.js +35 -15
  50. package/dist/runner/inpage/banner.d.ts +9 -1
  51. package/dist/runner/inpage/banner.js +27 -2
  52. package/dist/runner/inpage/caption.d.ts +3 -0
  53. package/dist/runner/inpage/caption.js +23 -0
  54. package/dist/runner/inpage/core.js +32 -9
  55. package/dist/runner/inpage/network.d.ts +15 -0
  56. package/dist/runner/inpage/network.js +217 -0
  57. package/dist/runner/inpage/panel-chrome.js +41 -1
  58. package/dist/runner/inpage/swipe-zoom.js +1 -1
  59. package/dist/runner/inpage/todos.js +6 -1
  60. package/dist/runner/main.js +9 -2
  61. package/dist/runner/network-capture.d.ts +9 -0
  62. package/dist/runner/network-capture.js +126 -0
  63. package/dist/runner/overlay-css.js +71 -7
  64. package/dist/runner/overlay-install.js +39 -2
  65. package/dist/runner/overlay-stage.js +5 -0
  66. package/dist/runner/rings.js +69 -45
  67. package/dist/runner/slides.js +14 -8
  68. package/dist/runner/step-mode.js +12 -0
  69. package/dist/runner/step-panels.js +9 -3
  70. package/dist/runner/teardown.js +16 -9
  71. package/dist/session/auto-explore-run.d.ts +5 -2
  72. package/dist/session/auto-explore-run.js +52 -36
  73. package/dist/{step-overlay.d.ts → session/step-overlay.d.ts} +1 -1
  74. package/dist/{step-overlay.js → session/step-overlay.js} +1 -1
  75. package/dist/trait.d.ts +1 -0
  76. package/dist/trait.js +15 -0
  77. package/dist/traverse/run.js +3 -22
  78. package/dist/ui/components/ring.js +4 -2
  79. package/dist/ui/overlay.css +36 -3
  80. package/examples/saucedemo/.waygraph-auto/00d147d1.log +21 -0
  81. package/examples/saucedemo/.waygraph-auto/0402cfcf.log +6 -0
  82. package/examples/saucedemo/.waygraph-auto/062b581f.log +20 -0
  83. package/examples/saucedemo/.waygraph-auto/0681582b.log +6 -0
  84. package/examples/saucedemo/.waygraph-auto/07f3e964.log +6 -0
  85. package/examples/saucedemo/.waygraph-auto/0868ae4d.log +0 -0
  86. package/examples/saucedemo/.waygraph-auto/0924ddaa.log +22 -0
  87. package/examples/saucedemo/.waygraph-auto/092d6173.log +5 -0
  88. package/examples/saucedemo/.waygraph-auto/09924510.log +0 -0
  89. package/examples/saucedemo/.waygraph-auto/0998c941.log +21 -0
  90. package/examples/saucedemo/.waygraph-auto/0bf74300.log +21 -0
  91. package/examples/saucedemo/.waygraph-auto/0c01fd29.log +4 -0
  92. package/examples/saucedemo/.waygraph-auto/0c302590.log +0 -0
  93. package/examples/saucedemo/.waygraph-auto/0dee62d6.log +5 -0
  94. package/examples/saucedemo/.waygraph-auto/0eb4c081.log +5 -0
  95. package/examples/saucedemo/.waygraph-auto/10fd431c.log +0 -0
  96. package/examples/saucedemo/.waygraph-auto/13c6fe3c.log +0 -0
  97. package/examples/saucedemo/.waygraph-auto/1581b677.log +0 -0
  98. package/examples/saucedemo/.waygraph-auto/161cc8dd.log +22 -0
  99. package/examples/saucedemo/.waygraph-auto/164761a5.log +6 -0
  100. package/examples/saucedemo/.waygraph-auto/1905ceb2.log +0 -0
  101. package/examples/saucedemo/.waygraph-auto/1b1d55c6.log +0 -0
  102. package/examples/saucedemo/.waygraph-auto/1b80fd24.log +6 -0
  103. package/examples/saucedemo/.waygraph-auto/1c30a3c2.log +0 -0
  104. package/examples/saucedemo/.waygraph-auto/1d90aa9a.log +0 -0
  105. package/examples/saucedemo/.waygraph-auto/1de7d889.log +0 -0
  106. package/examples/saucedemo/.waygraph-auto/1f233a4c.log +6 -0
  107. package/examples/saucedemo/.waygraph-auto/20e66801.log +0 -0
  108. package/examples/saucedemo/.waygraph-auto/20ffdb77.log +0 -0
  109. package/examples/saucedemo/.waygraph-auto/22048fff.log +4 -0
  110. package/examples/saucedemo/.waygraph-auto/22f1a704.log +5 -0
  111. package/examples/saucedemo/.waygraph-auto/239cced3.log +20 -0
  112. package/examples/saucedemo/.waygraph-auto/25204b46.log +4 -0
  113. package/examples/saucedemo/.waygraph-auto/25e2e90f.log +0 -0
  114. package/examples/saucedemo/.waygraph-auto/2708455e.log +22 -0
  115. package/examples/saucedemo/.waygraph-auto/272a96fd.log +20 -0
  116. package/examples/saucedemo/.waygraph-auto/28d7be5d.log +0 -0
  117. package/examples/saucedemo/.waygraph-auto/2a6a8266.log +6 -0
  118. package/examples/saucedemo/.waygraph-auto/2b3401cf.log +20 -0
  119. package/examples/saucedemo/.waygraph-auto/2ceccd6d.log +0 -0
  120. package/examples/saucedemo/.waygraph-auto/2f1b0c13.log +6 -0
  121. package/examples/saucedemo/.waygraph-auto/2f8d4073.log +6 -0
  122. package/examples/saucedemo/.waygraph-auto/30739278.log +6 -0
  123. package/examples/saucedemo/.waygraph-auto/31cb2e80.log +0 -0
  124. package/examples/saucedemo/.waygraph-auto/322d63cd.log +0 -0
  125. package/examples/saucedemo/.waygraph-auto/3239aa8a.log +6 -0
  126. package/examples/saucedemo/.waygraph-auto/326d87b7.log +6 -0
  127. package/examples/saucedemo/.waygraph-auto/3351c0b6.log +0 -0
  128. package/examples/saucedemo/.waygraph-auto/33df0770.log +0 -0
  129. package/examples/saucedemo/.waygraph-auto/340d624d.log +0 -0
  130. package/examples/saucedemo/.waygraph-auto/36367ccf.log +0 -0
  131. package/examples/saucedemo/.waygraph-auto/372536a5.log +6 -0
  132. package/examples/saucedemo/.waygraph-auto/3a412f3c.log +0 -0
  133. package/examples/saucedemo/.waygraph-auto/3a859bd7.log +0 -0
  134. package/examples/saucedemo/.waygraph-auto/3cb0add7.log +0 -0
  135. package/examples/saucedemo/.waygraph-auto/3e42f0d8.log +0 -0
  136. package/examples/saucedemo/.waygraph-auto/4144071d.log +0 -0
  137. package/examples/saucedemo/.waygraph-auto/4176a3c6.log +0 -0
  138. package/examples/saucedemo/.waygraph-auto/41d0793d.log +4 -0
  139. package/examples/saucedemo/.waygraph-auto/424b4d5d.log +0 -0
  140. package/examples/saucedemo/.waygraph-auto/43253aba.log +0 -0
  141. package/examples/saucedemo/.waygraph-auto/438c6c53.log +22 -0
  142. package/examples/saucedemo/.waygraph-auto/4477db12.log +0 -0
  143. package/examples/saucedemo/.waygraph-auto/4a1258b7.log +0 -0
  144. package/examples/saucedemo/.waygraph-auto/4adcd179.log +20 -0
  145. package/examples/saucedemo/.waygraph-auto/4c9d9b16.log +21 -0
  146. package/examples/saucedemo/.waygraph-auto/4da39c36.log +6 -0
  147. package/examples/saucedemo/.waygraph-auto/4dbefa7e.log +5 -0
  148. package/examples/saucedemo/.waygraph-auto/4efa7035.log +6 -0
  149. package/examples/saucedemo/.waygraph-auto/505affdc.log +4 -0
  150. package/examples/saucedemo/.waygraph-auto/51bcb60a.log +0 -0
  151. package/examples/saucedemo/.waygraph-auto/5291bc78.log +22 -0
  152. package/examples/saucedemo/.waygraph-auto/54274c39.log +5 -0
  153. package/examples/saucedemo/.waygraph-auto/5440ce7e.log +0 -0
  154. package/examples/saucedemo/.waygraph-auto/5738175f.log +22 -0
  155. package/examples/saucedemo/.waygraph-auto/57ce5643.log +22 -0
  156. package/examples/saucedemo/.waygraph-auto/5984426b.log +6 -0
  157. package/examples/saucedemo/.waygraph-auto/5a682e7c.log +22 -0
  158. package/examples/saucedemo/.waygraph-auto/5b79320c.log +21 -0
  159. package/examples/saucedemo/.waygraph-auto/5c55aaac.log +21 -0
  160. package/examples/saucedemo/.waygraph-auto/5d285cd3.log +0 -0
  161. package/examples/saucedemo/.waygraph-auto/5ed00b16.log +4 -0
  162. package/examples/saucedemo/.waygraph-auto/60b9c066.log +6 -0
  163. package/examples/saucedemo/.waygraph-auto/610dd127.log +0 -0
  164. package/examples/saucedemo/.waygraph-auto/61105500.log +5 -0
  165. package/examples/saucedemo/.waygraph-auto/6134afe8.log +20 -0
  166. package/examples/saucedemo/.waygraph-auto/62a0bdc9.log +22 -0
  167. package/examples/saucedemo/.waygraph-auto/6376fc15.log +0 -0
  168. package/examples/saucedemo/.waygraph-auto/6599cbca.log +22 -0
  169. package/examples/saucedemo/.waygraph-auto/67aaca30.log +0 -0
  170. package/examples/saucedemo/.waygraph-auto/68b10298.log +0 -0
  171. package/examples/saucedemo/.waygraph-auto/68be5e12.log +0 -0
  172. package/examples/saucedemo/.waygraph-auto/68df05a6.log +22 -0
  173. package/examples/saucedemo/.waygraph-auto/693f67c4.log +20 -0
  174. package/examples/saucedemo/.waygraph-auto/69ae030a.log +6 -0
  175. package/examples/saucedemo/.waygraph-auto/69e73f35.log +6 -0
  176. package/examples/saucedemo/.waygraph-auto/6b2333b0.log +5 -0
  177. package/examples/saucedemo/.waygraph-auto/6c4c3817.log +0 -0
  178. package/examples/saucedemo/.waygraph-auto/6c954911.log +0 -0
  179. package/examples/saucedemo/.waygraph-auto/6d65a439.log +5 -0
  180. package/examples/saucedemo/.waygraph-auto/6d700055.log +0 -0
  181. package/examples/saucedemo/.waygraph-auto/6ead848f.log +0 -0
  182. package/examples/saucedemo/.waygraph-auto/72675b2d.log +6 -0
  183. package/examples/saucedemo/.waygraph-auto/733dd260.log +5 -0
  184. package/examples/saucedemo/.waygraph-auto/75016486.log +0 -0
  185. package/examples/saucedemo/.waygraph-auto/752b01c6.log +22 -0
  186. package/examples/saucedemo/.waygraph-auto/75675227.log +6 -0
  187. package/examples/saucedemo/.waygraph-auto/75e2e658.log +0 -0
  188. package/examples/saucedemo/.waygraph-auto/76ac1a86.log +0 -0
  189. package/examples/saucedemo/.waygraph-auto/77605295.log +0 -0
  190. package/examples/saucedemo/.waygraph-auto/792671f4.log +22 -0
  191. package/examples/saucedemo/.waygraph-auto/79915adb.log +20 -0
  192. package/examples/saucedemo/.waygraph-auto/7a398774.log +6 -0
  193. package/examples/saucedemo/.waygraph-auto/7a72f66e.log +6 -0
  194. package/examples/saucedemo/.waygraph-auto/7a984334.log +4 -0
  195. package/examples/saucedemo/.waygraph-auto/7c6ee793.log +20 -0
  196. package/examples/saucedemo/.waygraph-auto/7c726dc4.log +22 -0
  197. package/examples/saucedemo/.waygraph-auto/7c72e8a5.log +4 -0
  198. package/examples/saucedemo/.waygraph-auto/7dbee625.log +22 -0
  199. package/examples/saucedemo/.waygraph-auto/7df66956.log +0 -0
  200. package/examples/saucedemo/.waygraph-auto/7e053160.log +0 -0
  201. package/examples/saucedemo/.waygraph-auto/7fcb512f.log +22 -0
  202. package/examples/saucedemo/.waygraph-auto/802a0b5b.log +0 -0
  203. package/examples/saucedemo/.waygraph-auto/80322e0b.log +0 -0
  204. package/examples/saucedemo/.waygraph-auto/80a4978e.log +6 -0
  205. package/examples/saucedemo/.waygraph-auto/81cfe480.log +22 -0
  206. package/examples/saucedemo/.waygraph-auto/832f5add.log +0 -0
  207. package/examples/saucedemo/.waygraph-auto/8337b6ad.log +0 -0
  208. package/examples/saucedemo/.waygraph-auto/8493928e.log +0 -0
  209. package/examples/saucedemo/.waygraph-auto/84dc6480.log +6 -0
  210. package/examples/saucedemo/.waygraph-auto/853bde43.log +0 -0
  211. package/examples/saucedemo/.waygraph-auto/86350ea6.log +22 -0
  212. package/examples/saucedemo/.waygraph-auto/86bb598a.log +0 -0
  213. package/examples/saucedemo/.waygraph-auto/86d09876.log +22 -0
  214. package/examples/saucedemo/.waygraph-auto/878ad01b.log +4 -0
  215. package/examples/saucedemo/.waygraph-auto/87c88ba5.log +0 -0
  216. package/examples/saucedemo/.waygraph-auto/87cb80ff.log +0 -0
  217. package/examples/saucedemo/.waygraph-auto/880b2e78.log +6 -0
  218. package/examples/saucedemo/.waygraph-auto/88527936.log +5 -0
  219. package/examples/saucedemo/.waygraph-auto/88eda676.log +0 -0
  220. package/examples/saucedemo/.waygraph-auto/893023ea.log +5 -0
  221. package/examples/saucedemo/.waygraph-auto/89416718.log +0 -0
  222. package/examples/saucedemo/.waygraph-auto/8996a857.log +6 -0
  223. package/examples/saucedemo/.waygraph-auto/8a08b68d.log +6 -0
  224. package/examples/saucedemo/.waygraph-auto/8a64ba0f.log +6 -0
  225. package/examples/saucedemo/.waygraph-auto/8b1cc2aa.log +6 -0
  226. package/examples/saucedemo/.waygraph-auto/8b73d13e.log +6 -0
  227. package/examples/saucedemo/.waygraph-auto/8d9e5cd2.log +21 -0
  228. package/examples/saucedemo/.waygraph-auto/8ec7d260.log +0 -0
  229. package/examples/saucedemo/.waygraph-auto/8ed43279.log +0 -0
  230. package/examples/saucedemo/.waygraph-auto/93acae32.log +5 -0
  231. package/examples/saucedemo/.waygraph-auto/96321a08.log +0 -0
  232. package/examples/saucedemo/.waygraph-auto/9742b6c2.log +6 -0
  233. package/examples/saucedemo/.waygraph-auto/99cc93eb.log +6 -0
  234. package/examples/saucedemo/.waygraph-auto/9cbfbedc.log +0 -0
  235. package/examples/saucedemo/.waygraph-auto/9dc147d2.log +22 -0
  236. package/examples/saucedemo/.waygraph-auto/a215a395.log +22 -0
  237. package/examples/saucedemo/.waygraph-auto/a23b7086.log +4 -0
  238. package/examples/saucedemo/.waygraph-auto/a35bd5ec.log +0 -0
  239. package/examples/saucedemo/.waygraph-auto/a68995e9.log +22 -0
  240. package/examples/saucedemo/.waygraph-auto/a6e4f936.log +22 -0
  241. package/examples/saucedemo/.waygraph-auto/a7da862b.log +0 -0
  242. package/examples/saucedemo/.waygraph-auto/a82e2a48.log +0 -0
  243. package/examples/saucedemo/.waygraph-auto/a952eb91.log +0 -0
  244. package/examples/saucedemo/.waygraph-auto/a9559653.log +5 -0
  245. package/examples/saucedemo/.waygraph-auto/aa478de2.log +0 -0
  246. package/examples/saucedemo/.waygraph-auto/ac350fc7.log +20 -0
  247. package/examples/saucedemo/.waygraph-auto/acc1b63a.log +0 -0
  248. package/examples/saucedemo/.waygraph-auto/ad12d191.log +0 -0
  249. package/examples/saucedemo/.waygraph-auto/b04638f4.log +6 -0
  250. package/examples/saucedemo/.waygraph-auto/b48863e5.log +22 -0
  251. package/examples/saucedemo/.waygraph-auto/b56968e1.log +6 -0
  252. package/examples/saucedemo/.waygraph-auto/b64e0620.log +20 -0
  253. package/examples/saucedemo/.waygraph-auto/b86a6218.log +6 -0
  254. package/examples/saucedemo/.waygraph-auto/b8e9e956.log +22 -0
  255. package/examples/saucedemo/.waygraph-auto/b9b310ff.log +21 -0
  256. package/examples/saucedemo/.waygraph-auto/bc111745.log +22 -0
  257. package/examples/saucedemo/.waygraph-auto/bf7a77a2.log +0 -0
  258. package/examples/saucedemo/.waygraph-auto/c0d6f353.log +21 -0
  259. package/examples/saucedemo/.waygraph-auto/c0febcf2.log +20 -0
  260. package/examples/saucedemo/.waygraph-auto/c4c52998.log +6 -0
  261. package/examples/saucedemo/.waygraph-auto/c809ceb4.log +22 -0
  262. package/examples/saucedemo/.waygraph-auto/ca6de7e7.log +0 -0
  263. package/examples/saucedemo/.waygraph-auto/ca8561bc.log +0 -0
  264. package/examples/saucedemo/.waygraph-auto/cb86d45b.log +0 -0
  265. package/examples/saucedemo/.waygraph-auto/cb9a1978.log +6 -0
  266. package/examples/saucedemo/.waygraph-auto/cbbc689c.log +6 -0
  267. package/examples/saucedemo/.waygraph-auto/cd88364b.log +0 -0
  268. package/examples/saucedemo/.waygraph-auto/cd919e1d.log +0 -0
  269. package/examples/saucedemo/.waygraph-auto/cfff9eef.log +20 -0
  270. package/examples/saucedemo/.waygraph-auto/d0f59b21.log +4 -0
  271. package/examples/saucedemo/.waygraph-auto/d1195079.log +20 -0
  272. package/examples/saucedemo/.waygraph-auto/d2ef067a.log +5 -0
  273. package/examples/saucedemo/.waygraph-auto/d425471f.log +6 -0
  274. package/examples/saucedemo/.waygraph-auto/d5293921.log +0 -0
  275. package/examples/saucedemo/.waygraph-auto/d62a22c2.log +21 -0
  276. package/examples/saucedemo/.waygraph-auto/d6d1761f.log +22 -0
  277. package/examples/saucedemo/.waygraph-auto/d6d5f411.log +22 -0
  278. package/examples/saucedemo/.waygraph-auto/d6df2771.log +6 -0
  279. package/examples/saucedemo/.waygraph-auto/d7075012.log +21 -0
  280. package/examples/saucedemo/.waygraph-auto/d9ddc297.log +0 -0
  281. package/examples/saucedemo/.waygraph-auto/db4ac845.log +0 -0
  282. package/examples/saucedemo/.waygraph-auto/db6d7774.log +0 -0
  283. package/examples/saucedemo/.waygraph-auto/db839827.log +5 -0
  284. package/examples/saucedemo/.waygraph-auto/dde5e859.log +22 -0
  285. package/examples/saucedemo/.waygraph-auto/de8cac58.log +0 -0
  286. package/examples/saucedemo/.waygraph-auto/dedfcb18.log +0 -0
  287. package/examples/saucedemo/.waygraph-auto/def4d9b1.log +0 -0
  288. package/examples/saucedemo/.waygraph-auto/e1549e40.log +0 -0
  289. package/examples/saucedemo/.waygraph-auto/e1b0676d.log +21 -0
  290. package/examples/saucedemo/.waygraph-auto/e5111463.log +0 -0
  291. package/examples/saucedemo/.waygraph-auto/e5fc1d7c.log +5 -0
  292. package/examples/saucedemo/.waygraph-auto/e6fd2202.log +0 -0
  293. package/examples/saucedemo/.waygraph-auto/edaa806d.log +0 -0
  294. package/examples/saucedemo/.waygraph-auto/edaf33de.log +0 -0
  295. package/examples/saucedemo/.waygraph-auto/edd40cbb.log +20 -0
  296. package/examples/saucedemo/.waygraph-auto/eddfbffc.log +6 -0
  297. package/examples/saucedemo/.waygraph-auto/ee9fa1ad.log +5 -0
  298. package/examples/saucedemo/.waygraph-auto/ef319474.log +22 -0
  299. package/examples/saucedemo/.waygraph-auto/f28eee8d.log +0 -0
  300. package/examples/saucedemo/.waygraph-auto/f33bde90.log +0 -0
  301. package/examples/saucedemo/.waygraph-auto/f6ba7cb4.log +6 -0
  302. package/examples/saucedemo/.waygraph-auto/f7ac4d62.log +20 -0
  303. package/examples/saucedemo/.waygraph-auto/f929bb79.log +0 -0
  304. package/examples/saucedemo/.waygraph-auto/f92d4c6c.log +22 -0
  305. package/examples/saucedemo/.waygraph-auto/f92faf40.log +5 -0
  306. package/examples/saucedemo/.waygraph-auto/fa784369.log +21 -0
  307. package/examples/saucedemo/.waygraph-auto/fb55f723.log +20 -0
  308. package/examples/saucedemo/.waygraph-auto/fba3b738.log +0 -0
  309. package/examples/saucedemo/.waygraph-auto/fdf66b74.log +0 -0
  310. package/examples/saucedemo/.waygraph-auto/ffdf2854.log +6 -0
  311. package/examples/saucedemo/README.md +13 -2
  312. package/examples/saucedemo/package.json +4 -0
  313. package/examples/saucedemo/src/flows/api-demo.flow.ts +37 -0
  314. package/examples/saucedemo/src/flows/checkout.flow.ts +34 -11
  315. package/package.json +5 -3
  316. package/templates/scaffold/src/flows/shop.flow.ts +42 -27
  317. package/dist/auto-explore-run.d.ts +0 -37
  318. package/dist/auto-explore-run.js +0 -670
  319. package/dist/auto-explore.d.ts +0 -57
  320. package/dist/auto-explore.js +0 -376
  321. package/dist/auto-session-ipc.d.ts +0 -150
  322. package/dist/auto-session-ipc.js +0 -497
  323. package/dist/block-inject.d.ts +0 -15
  324. package/dist/block-inject.js +0 -91
  325. package/dist/browser.d.ts +0 -15
  326. package/dist/browser.js +0 -29
  327. package/dist/coverage-gap.d.ts +0 -11
  328. package/dist/coverage-gap.js +0 -119
  329. package/dist/engine.d.ts +0 -12
  330. package/dist/engine.js +0 -13
  331. package/dist/graph.d.ts +0 -92
  332. package/dist/graph.js +0 -467
  333. package/dist/highlight-shorthand.d.ts +0 -24
  334. package/dist/highlight-shorthand.js +0 -30
  335. package/dist/map-check.d.ts +0 -18
  336. package/dist/map-check.js +0 -140
  337. package/dist/overlay-beacon.d.ts +0 -44
  338. package/dist/overlay-beacon.js +0 -85
  339. package/dist/pilot.d.ts +0 -54
  340. package/dist/pilot.js +0 -80
  341. package/dist/practices-check.d.ts +0 -14
  342. package/dist/practices-check.js +0 -195
  343. package/dist/traverse-coverage.d.ts +0 -59
  344. package/dist/traverse-coverage.js +0 -127
  345. package/dist/traverse-lease.d.ts +0 -18
  346. package/dist/traverse-lease.js +0 -62
  347. package/dist/traverse-run.d.ts +0 -47
  348. package/dist/traverse-run.js +0 -439
  349. package/dist/ui/compose.d.ts +0 -4
  350. package/dist/ui/compose.js +0 -7
  351. /package/dist/{verbose-log.d.ts → auto-session/verbose-log.d.ts} +0 -0
  352. /package/dist/{verbose-log.js → auto-session/verbose-log.js} +0 -0
  353. /package/dist/{agent-dive.d.ts → commands/agent-dive-scaffold.d.ts} +0 -0
  354. /package/dist/{engine/core.d.ts → core/block.d.ts} +0 -0
  355. /package/dist/{engine → core}/blocks/nav.d.ts +0 -0
  356. /package/dist/{engine → core}/blocks/page.d.ts +0 -0
  357. /package/dist/{engine → core}/branch-regression.d.ts +0 -0
  358. /package/dist/{engine → core}/compose.d.ts +0 -0
  359. /package/dist/{engine → core}/config.d.ts +0 -0
  360. /package/dist/{engine → core}/config.js +0 -0
  361. /package/dist/{engine → core}/flow.d.ts +0 -0
  362. /package/dist/{engine → core}/locate.d.ts +0 -0
  363. /package/dist/{engine → core}/locate.js +0 -0
  364. /package/dist/{engine → core}/run-graph.d.ts +0 -0
@@ -242,6 +242,21 @@ export async function applyDeviceToPage(page, device, sync) {
242
242
  } catch {
243
243
  from = null;
244
244
  }
245
+ // Non-headless (no --video) used to literally resize the real OS browser window/viewport to
246
+ // each device's pixel size - a real, confirmed complaint: it didn't look like the same animated
247
+ // device-shell bezel the --video path already has, just a plain resize. Both now use the exact
248
+ // same applyVideoDeviceStage bezel technique - the "stage" (the fixed outer viewport the shell is
249
+ // centered within) is the recordVideo canvas size when recording, or the window's own size at
250
+ // the FIRST device switch when not (captured once, persisted on the page - the window itself is
251
+ // only really resized that one time, to establish a stable stage; every device switch after that
252
+ // paints the animated shell inside it instead of resizing the window again).
253
+ let establishingHeadedStage = false;
254
+ if (!videoStage && !page.__wgHeadedStage) {
255
+ page.__wgHeadedStage =
256
+ from && from.width > 0 && from.height > 0 ? { width: from.width, height: from.height } : { width: 1280, height: 720 };
257
+ establishingHeadedStage = true;
258
+ }
259
+ const stage = videoStage || page.__wgHeadedStage;
245
260
  const announce = mode === "set" || mode === "clear";
246
261
  const toDesktop =
247
262
  mode === "clear" || (d.preset === "desktop" && !d.touchMode);
@@ -275,13 +290,18 @@ export async function applyDeviceToPage(page, device, sync) {
275
290
  page.__wgDeviceOrient = nextOrient;
276
291
  page.__wgDevicePreset = toDesktop ? "desktop" : d.preset || "";
277
292
 
278
- if (videoStage) {
279
- // Lock Playwright viewport to the recordVideo size so frames fill the
280
- // .webm; center the device shell inside (OS window centering alone does not).
281
- // Do NOT fitWindow to the device size - that shrinks the viewport below the
282
- // recordVideo canvas and Playwright pads the .webm with grey (top-left bias).
293
+ if (stage) {
294
+ // Lock the Playwright viewport to the stage size so frames/window fill it; center the device
295
+ // shell inside (OS window centering alone does not). Do NOT fitWindow to the device size -
296
+ // that shrinks the viewport below the stage and (when recording) pads the .webm with grey
297
+ // (top-left bias). Headed-without-video reuses this exact technique (see `stage`'s own
298
+ // comment above) - the real OS window is only ever resized once, right here, to establish the
299
+ // stage itself; every device switch after that paints the animated shell inside it instead.
300
+ if (!videoStage && establishingHeadedStage) {
301
+ await fitWindowToDeviceViewport(page, stage, { maximize: false }).catch(() => {});
302
+ }
283
303
  try {
284
- await realSet(videoStage);
304
+ await realSet(stage);
285
305
  } catch {
286
306
  /* ignore */
287
307
  }
@@ -290,22 +310,22 @@ export async function applyDeviceToPage(page, device, sync) {
290
310
  // Zoom already cleared above. Full-bleed desktop shell (no matte frame).
291
311
  // Shutter-out: soft rounded -> radius 0, then flat edge-to-edge.
292
312
  const desk = {
293
- width: videoStage.width,
294
- height: videoStage.height,
313
+ width: stage.width,
314
+ height: stage.height,
295
315
  };
296
316
  page.__wgDeviceShell = { ...desk };
297
- await applyVideoDeviceStage(page, desk, videoStage, {
317
+ await applyVideoDeviceStage(page, desk, stage, {
298
318
  clear: false,
299
319
  shutterOut: true,
300
320
  desktopFlat: true,
301
321
  });
302
322
  try {
303
- await realSet(videoStage);
323
+ await realSet(stage);
304
324
  } catch {
305
325
  /* ignore */
306
326
  }
307
327
  } else {
308
- // Lerp shell size when switching mobile <-> tablet mid-video.
328
+ // Lerp shell size when switching mobile <-> tablet mid-run.
309
329
  const firstDevice = !page.__wgDeviceShell;
310
330
  if (
311
331
  announce &&
@@ -322,22 +342,22 @@ export async function applyDeviceToPage(page, device, sync) {
322
342
  width: Math.round(shellFrom.width + (target.width - shellFrom.width) * e),
323
343
  height: Math.round(shellFrom.height + (target.height - shellFrom.height) * e),
324
344
  };
325
- await applyVideoDeviceStage(page, mid, videoStage, {
345
+ await applyVideoDeviceStage(page, mid, stage, {
326
346
  clear: false,
327
347
  enterIn: i === 1 && firstDevice,
328
348
  });
329
349
  if (i < steps) await new Promise((r) => setTimeout(r, stepMs));
330
350
  }
331
351
  } else {
332
- await applyVideoDeviceStage(page, target, videoStage, {
352
+ await applyVideoDeviceStage(page, target, stage, {
333
353
  clear: false,
334
354
  enterIn: firstDevice || announce,
335
355
  });
336
356
  }
337
357
  page.__wgDeviceShell = { ...target };
338
- // Re-assert stage size after any prior non-video fitWindow.
358
+ // Re-assert stage size after any prior fitWindow.
339
359
  try {
340
- await realSet(videoStage);
360
+ await realSet(stage);
341
361
  } catch {
342
362
  /* ignore */
343
363
  }
@@ -8,6 +8,14 @@ export function installBanner(args: {
8
8
  todoPos?: string | undefined;
9
9
  envAutoplay?: boolean | undefined;
10
10
  todoDockUi?: unknown;
11
- bannerUi?: { hidden?: boolean | undefined; collision?: boolean | undefined; pos?: string | undefined } | undefined;
11
+ bannerUi?:
12
+ | {
13
+ hidden?: boolean | undefined;
14
+ collision?: boolean | undefined;
15
+ pos?: string | undefined;
16
+ /** Title-change fade duration in ms (default 220); 0 = instant swap, no fade. */
17
+ captionFadeMs?: number | undefined;
18
+ }
19
+ | undefined;
12
20
  tag?: string | undefined;
13
21
  }): void;
@@ -43,14 +43,31 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
43
43
  __wgAdd(banner);
44
44
  } else {
45
45
  // Fixture / episode title changes every step - update in place
46
- // (banner is created once; do not leave the first step's text stuck).
46
+ // (banner is created once; do not leave the first step's text stuck). Fades out/in
47
+ // instead of an instant swap, so a title change reads as a deliberate beat, not a
48
+ // flicker - opt-out (or re-tune) via bannerUi.captionFadeMs, 0 = instant.
47
49
  let text = banner.querySelector(".wg-banner-text");
48
50
  if (!text) {
49
51
  text = document.createElement("span");
50
52
  text.className = "wg-banner-text";
51
53
  banner.appendChild(text);
52
54
  }
53
- text.textContent = title;
55
+ if (text.textContent !== title) {
56
+ const fadeMs =
57
+ bannerUi && Number.isFinite(Number(bannerUi.captionFadeMs))
58
+ ? Math.max(0, Number(bannerUi.captionFadeMs))
59
+ : 220;
60
+ if (fadeMs <= 0 || !text.textContent) {
61
+ text.textContent = title;
62
+ } else {
63
+ text.style.transition = "opacity " + fadeMs + "ms ease";
64
+ text.style.opacity = "0";
65
+ setTimeout(() => {
66
+ text.textContent = title;
67
+ text.style.opacity = "1";
68
+ }, fadeMs);
69
+ }
70
+ }
54
71
  }
55
72
  }
56
73
  // Authored banner UX (StubCtx.titlePos / bannerUi): applied every step, wins over click/env.
@@ -107,6 +124,14 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
107
124
  if (b.dataset.home) b.dataset.pos = b.dataset.home;
108
125
  delete b.dataset.moved;
109
126
  };
127
+ // Dim the banner while a ring caption is the focus - same "auto opacity" effect the todo
128
+ // dock already has via __wgTodosSetBehind, extended to the banner so both floating chrome
129
+ // pieces step back the same way instead of only one of them fading.
130
+ window.__wgBannerSetBehind = (on) => {
131
+ const b = __wgById("wg-banner");
132
+ if (!b) return;
133
+ b.classList.toggle("wg-banner-behind", !!on);
134
+ };
110
135
  // Tab title/favicon: a real navigation resets document.title and any
111
136
  // <link rel="icon"> the new document brings, so re-check (not
112
137
  // re-append) on every call instead of a one-time flag.
@@ -0,0 +1,3 @@
1
+ /** In-page installer (page.evaluate target) - see caption.js's own header. */
2
+ export function showCaption(text: string): void;
3
+ export function hideCaption(): void;
@@ -0,0 +1,23 @@
1
+ // In-page installer (page.evaluate target) - must stay self-contained, no module-scope closure.
2
+ // Bottom narration caption - a white rounded card, not the dark zsign-ported scrim this started as
3
+ // (see ui/css/caption.css's own header); narration-timeline/TTS sync not ported yet.
4
+ export function showCaption(text) {
5
+ let bar = __wgById("wg-caption-bar");
6
+ if (!bar) {
7
+ bar = document.createElement("div");
8
+ bar.id = "wg-caption-bar";
9
+ bar.setAttribute("data-wg-ui", "1");
10
+ const span = document.createElement("span");
11
+ span.className = "wg-caption-text";
12
+ bar.appendChild(span);
13
+ __wgAdd(bar);
14
+ }
15
+ const span = bar.querySelector(".wg-caption-text");
16
+ span.textContent = text;
17
+ bar.classList.add("wg-in");
18
+ }
19
+
20
+ export function hideCaption() {
21
+ const bar = __wgById("wg-caption-bar");
22
+ if (bar) bar.classList.remove("wg-in");
23
+ }
@@ -78,7 +78,25 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
78
78
  const lh = ringLabel.offsetHeight;
79
79
  let labelLeft = left;
80
80
  let labelTop = top + height + 8;
81
- if (labelTop + lh > vh - margin) labelTop = top - lh - 8;
81
+ const aboveTop = top - lh - 8;
82
+ if (labelTop + lh > vh - margin) {
83
+ labelTop = aboveTop;
84
+ } else {
85
+ // Below the ringed box is often the NEXT form field in a tightly stacked list (e.g.
86
+ // saucedemo's checkout "First Name" / "Last Name" / "Zip" inputs) - a fixed +8px gap
87
+ // has no idea that's there and the label just sits on top of it. Sample a few points
88
+ // under the would-be label and flip above if any land on real page content (not our
89
+ // own ring/label elements, which are the only things expected there otherwise).
90
+ const probe = (x, y) => {
91
+ const el = document.elementFromPoint(x, y);
92
+ return el && el.id !== ringId && el.id !== labelId && !(el.closest && el.closest("#wg-root"));
93
+ };
94
+ const hitsPageContent =
95
+ probe(labelLeft + 2, labelTop + 2) ||
96
+ probe(labelLeft + lw - 2, labelTop + 2) ||
97
+ probe(labelLeft + 2, labelTop + lh - 2);
98
+ if (hitsPageContent && aboveTop >= margin) labelTop = aboveTop;
99
+ }
82
100
  if (labelTop < margin) labelTop = margin;
83
101
  if (labelLeft + lw > vw - margin) labelLeft = Math.max(margin, vw - margin - lw);
84
102
  if (labelLeft < margin) labelLeft = margin;
@@ -136,6 +154,7 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
136
154
  if (!box) return;
137
155
  window.__wgPaintRingAt("wg-ring", "wg-ring-label", box, label, tone, style);
138
156
  if (window.__wgTodosSetBehind) window.__wgTodosSetBehind(true);
157
+ if (window.__wgBannerSetBehind) window.__wgBannerSetBehind(true);
139
158
  if (window.__wgTodosAvoidRingCollision) window.__wgTodosAvoidRingCollision(box);
140
159
  if (window.__wgBannerAvoidRing) window.__wgBannerAvoidRing(box);
141
160
  };
@@ -188,22 +207,25 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
188
207
  break;
189
208
  }
190
209
  };
191
- /** Live-follow a selector with rAF (accurate under device shell scale). */
210
+ /** Live-follow a resolved element with rAF (accurate under device shell scale). */
192
211
  window.__wgStopRingFollow = () => {
193
212
  if (window.__wgRingFollowRaf) {
194
213
  cancelAnimationFrame(window.__wgRingFollowRaf);
195
214
  window.__wgRingFollowRaf = 0;
196
215
  }
197
- window.__wgRingFollowSel = "";
216
+ window.__wgRingFollowEl = null;
198
217
  };
199
- window.__wgFollowRing = (sel, label, tone, style, focus) => {
218
+ // `el` is a real DOM element (a Playwright ElementHandle unwrapped by evaluate() - see
219
+ // rings.js's showRing), not a selector string - >> piercing / :has-text() are Playwright's
220
+ // own selector-engine syntax, which document.querySelector has no way to understand, so
221
+ // resolution happens once on the Node side via page.locator(), before this ever runs.
222
+ window.__wgFollowRing = (el, label, tone, style, focus) => {
200
223
  window.__wgStopRingFollow();
201
- if (!sel) return;
202
- window.__wgRingFollowSel = sel;
224
+ if (!el) return;
225
+ window.__wgRingFollowEl = el;
203
226
  const tick = () => {
204
- if (window.__wgRingFollowSel !== sel) return;
205
- const el = document.querySelector(sel);
206
- if (!el) {
227
+ if (window.__wgRingFollowEl !== el) return;
228
+ if (!el.isConnected) {
207
229
  window.__wgRingFollowRaf = requestAnimationFrame(tick);
208
230
  return;
209
231
  }
@@ -244,6 +266,7 @@ export function installCore({ title, favicon, bannerPos, todoPos, envAutoplay, t
244
266
  if (ringLabel) ringLabel.style.opacity = "0";
245
267
  if (window.__wgClearFocus) window.__wgClearFocus();
246
268
  if (window.__wgTodosSetBehind) window.__wgTodosSetBehind(false);
269
+ if (window.__wgBannerSetBehind) window.__wgBannerSetBehind(false);
247
270
  if (window.__wgBannerRestore) window.__wgBannerRestore();
248
271
  window.__wgTodoCollisionLocked = false;
249
272
  __wgQA(".wg-todo-dock[data-tucked], #wg-todo-dock[data-tucked]").forEach((el) => {
@@ -0,0 +1,15 @@
1
+ /** In-page installer (page.evaluate target) - see network.js's own header. */
2
+ export interface NetworkEntry {
3
+ method: string;
4
+ url: string;
5
+ status: number;
6
+ ok: boolean;
7
+ ms?: number | undefined;
8
+ reqHeaders?: Record<string, string> | undefined;
9
+ resHeaders?: Record<string, string> | undefined;
10
+ reqBody?: string | undefined;
11
+ resBody?: string | undefined;
12
+ }
13
+ export function addNetworkEntry(entry: NetworkEntry): void;
14
+ export function setNetworkTabVisible(visible: boolean): void;
15
+ export function clearNetworkLog(): void;
@@ -0,0 +1,217 @@
1
+ // In-page installer (page.evaluate target) - must stay self-contained, no module-scope closure
2
+ // (page.evaluate serializes ONLY the passed function's own source, not sibling top-level
3
+ // functions in this file - every helper below is nested inside addNetworkEntry itself for exactly
4
+ // that reason; a row's click handler still works after addNetworkEntry returns because it's a
5
+ // closure over ITS OWN invocation's nested helpers, not a reference to module scope).
6
+ //
7
+ // A real network-tab overlay (`#wg-network-log`): the DevTools Network panel itself can't be
8
+ // embedded (it lives in browser chrome, not reachable from automation), but every entry's real
9
+ // data is - this renders that, on-page: method, url, status, and (click a row) request/response
10
+ // headers + bodies + a "copy as cURL" command, a Postman-style inspector for both real page
11
+ // traffic (installNetworkCapture, network-capture.js) and defineApiBlock's own page.request calls.
12
+ export function addNetworkEntry(entry) {
13
+ // No-op outside a demo/pilot/auto run - ensureShadowRoot() (and its __wgById/__wgAdd globals)
14
+ // is never installed for a plain `waygraph run`/Playwright test, and this must not throw there.
15
+ if (typeof __wgById !== "function" || typeof __wgAdd !== "function") return;
16
+
17
+ function esc(s) {
18
+ const d = document.createElement("div");
19
+ d.textContent = String(s == null ? "" : s);
20
+ return d.innerHTML;
21
+ }
22
+
23
+ function methodClass(method) {
24
+ const m = (method || "GET").toUpperCase();
25
+ if (m === "GET") return "get";
26
+ if (m === "POST") return "post";
27
+ if (m === "PUT" || m === "PATCH") return "put";
28
+ if (m === "DELETE") return "delete";
29
+ return "other";
30
+ }
31
+
32
+ function toCurl(e) {
33
+ let cmd = "curl -X " + (e.method || "GET") + " '" + String(e.url || "").replace(/'/g, "'\\''") + "'";
34
+ const headers = e.reqHeaders || {};
35
+ for (const k of Object.keys(headers)) {
36
+ if (/^:/.test(k)) continue; // HTTP/2 pseudo-headers - not valid curl -H input
37
+ cmd += " \\\n -H '" + k + ": " + String(headers[k]).replace(/'/g, "'\\''") + "'";
38
+ }
39
+ if (e.reqBody) cmd += " \\\n --data '" + String(e.reqBody).replace(/'/g, "'\\''") + "'";
40
+ return cmd;
41
+ }
42
+
43
+ function renderHeaders(headers) {
44
+ const h = headers || {};
45
+ const keys = Object.keys(h);
46
+ if (keys.length === 0) return '<div class="wg-net-empty">(none)</div>';
47
+ return (
48
+ '<table class="wg-net-headers">' +
49
+ keys.map((k) => "<tr><td>" + esc(k) + "</td><td>" + esc(h[k]) + "</td></tr>").join("") +
50
+ "</table>"
51
+ );
52
+ }
53
+
54
+ function renderBody(body) {
55
+ if (body === undefined || body === null || body === "") return '<div class="wg-net-empty">(empty)</div>';
56
+ let text = body;
57
+ try {
58
+ text = JSON.stringify(JSON.parse(body), null, 2);
59
+ } catch {
60
+ /* not JSON - show raw */
61
+ }
62
+ return "<pre class=\"wg-net-body\">" + esc(String(text).slice(0, 4000)) + "</pre>";
63
+ }
64
+
65
+ function renderDetail(e) {
66
+ return (
67
+ '<div class="wg-net-detail-section"><h4>Request headers</h4>' +
68
+ renderHeaders(e.reqHeaders) +
69
+ "</div>" +
70
+ (e.reqBody
71
+ ? '<div class="wg-net-detail-section"><h4>Request body</h4>' + renderBody(e.reqBody) + "</div>"
72
+ : "") +
73
+ '<div class="wg-net-detail-section"><h4>Response headers</h4>' +
74
+ renderHeaders(e.resHeaders) +
75
+ "</div>" +
76
+ '<div class="wg-net-detail-section"><h4>Response body</h4>' +
77
+ renderBody(e.resBody) +
78
+ "</div>" +
79
+ '<div class="wg-net-detail-section"><h4>cURL</h4>' +
80
+ '<pre class="wg-net-body wg-net-curl">' +
81
+ esc(toCurl(e)) +
82
+ "</pre>" +
83
+ '<button type="button" class="wg-net-copy" data-copy="1">Copy as cURL</button></div>'
84
+ );
85
+ }
86
+
87
+ let panel = __wgById("wg-network-log");
88
+ if (!panel) {
89
+ panel = document.createElement("div");
90
+ panel.id = "wg-network-log";
91
+ panel.setAttribute("data-wg-ui", "1");
92
+ const header = document.createElement("div");
93
+ header.className = "wg-net-header";
94
+ const title = document.createElement("span");
95
+ title.className = "wg-net-title";
96
+ title.textContent = "Network";
97
+ const count = document.createElement("span");
98
+ count.className = "wg-net-count";
99
+ count.textContent = "0";
100
+ const toggle = document.createElement("button");
101
+ toggle.type = "button";
102
+ toggle.className = "wg-net-collapse";
103
+ toggle.textContent = "−"; // minus
104
+ toggle.addEventListener("click", (ev) => {
105
+ ev.stopPropagation();
106
+ panel.classList.toggle("wg-net-collapsed");
107
+ toggle.textContent = panel.classList.contains("wg-net-collapsed") ? "+" : "−";
108
+ });
109
+ header.appendChild(title);
110
+ header.appendChild(count);
111
+ header.appendChild(toggle);
112
+ const list = document.createElement("ol");
113
+ list.className = "wg-net-list";
114
+ panel.appendChild(header);
115
+ panel.appendChild(list);
116
+ __wgAdd(panel);
117
+ }
118
+
119
+ const w = window;
120
+ w.__wgNetworkEntries = w.__wgNetworkEntries || [];
121
+ w.__wgNetworkEntries.push(entry);
122
+ while (w.__wgNetworkEntries.length > 30) w.__wgNetworkEntries.shift();
123
+
124
+ const list = panel.querySelector(".wg-net-list");
125
+ const row = document.createElement("li");
126
+ row.className = "wg-net-row";
127
+ row.dataset.ok = entry.ok ? "1" : "0";
128
+ let path = entry.url;
129
+ try {
130
+ const u = new URL(entry.url);
131
+ path = u.pathname + u.search;
132
+ } catch {
133
+ /* not an absolute URL - show as given */
134
+ }
135
+ row.innerHTML =
136
+ '<span class="wg-net-method wg-net-method-' +
137
+ methodClass(entry.method) +
138
+ '">' +
139
+ esc((entry.method || "GET").toUpperCase()) +
140
+ '</span><span class="wg-net-path" title="' +
141
+ esc(entry.url) +
142
+ '">' +
143
+ esc(path) +
144
+ '</span><span class="wg-net-status">' +
145
+ esc(entry.status) +
146
+ (entry.ms !== undefined ? '</span><span class="wg-net-ms">' + esc(entry.ms) + "ms</span>" : "</span>");
147
+ row.addEventListener("click", () => {
148
+ const open = row.classList.contains("wg-net-open");
149
+ __wgQA(".wg-net-row.wg-net-open").forEach((r) => {
150
+ r.classList.remove("wg-net-open");
151
+ const d = r.nextElementSibling;
152
+ if (d && d.classList && d.classList.contains("wg-net-detail")) d.remove();
153
+ });
154
+ if (open) return;
155
+ row.classList.add("wg-net-open");
156
+ const detail = document.createElement("li");
157
+ detail.className = "wg-net-detail";
158
+ detail.innerHTML = renderDetail(entry);
159
+ const copyBtn = detail.querySelector("[data-copy]");
160
+ if (copyBtn) {
161
+ copyBtn.addEventListener("click", (ev) => {
162
+ ev.stopPropagation();
163
+ const text = toCurl(entry);
164
+ if (navigator.clipboard && navigator.clipboard.writeText) {
165
+ navigator.clipboard.writeText(text).catch(() => {});
166
+ }
167
+ copyBtn.textContent = "Copied!";
168
+ setTimeout(() => {
169
+ copyBtn.textContent = "Copy as cURL";
170
+ }, 1200);
171
+ });
172
+ }
173
+ row.after(detail);
174
+ });
175
+ list.appendChild(row);
176
+ while (list.children.length > 30) list.removeChild(list.firstChild);
177
+ const countEl = panel.querySelector(".wg-net-count");
178
+ if (countEl) countEl.textContent = String(w.__wgNetworkEntries.length);
179
+ // Always captured, only shown when explicitly turned on (ctx.showNetworkTab(); default hidden -
180
+ // see StubCtx's own doc comment) - the DOM/row still gets built either way, so toggling visible
181
+ // later shows the full history immediately, not just entries captured after that point.
182
+ if (w.__wgNetworkTabVisible) {
183
+ panel.classList.remove("wg-out");
184
+ void panel.offsetWidth;
185
+ panel.classList.add("wg-in");
186
+ void row.offsetWidth;
187
+ row.classList.add("wg-in");
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Shows or hides the network-tab panel - capture keeps happening either way (addNetworkEntry
193
+ * always builds the DOM row; this only toggles whether the panel itself is visible). Safe to call
194
+ * before any entry exists yet - it just remembers the flag for addNetworkEntry to check later.
195
+ */
196
+ export function setNetworkTabVisible(visible) {
197
+ if (typeof __wgById !== "function") return;
198
+ window.__wgNetworkTabVisible = !!visible;
199
+ const panel = __wgById("wg-network-log");
200
+ if (!panel) return;
201
+ if (visible) {
202
+ panel.classList.remove("wg-out");
203
+ panel.classList.add("wg-in");
204
+ __wgQA(".wg-net-row").forEach((r) => r.classList.add("wg-in"));
205
+ } else {
206
+ panel.classList.remove("wg-in");
207
+ panel.classList.add("wg-out");
208
+ }
209
+ }
210
+
211
+ /** Clears every captured entry and removes the panel - a fresh navigation/session starting over. */
212
+ export function clearNetworkLog() {
213
+ if (typeof __wgById !== "function") return;
214
+ window.__wgNetworkEntries = [];
215
+ const panel = __wgById("wg-network-log");
216
+ if (panel) panel.remove();
217
+ }
@@ -60,6 +60,40 @@ export function installPanelChrome({ title, favicon, bannerPos, todoPos, envAuto
60
60
  ensureChrome();
61
61
  const stepLabel = opts.stepLabel || panel.dataset.wgStepLabel || "";
62
62
  if (stepLabel) panel.dataset.wgStepLabel = stepLabel;
63
+ if (opts.fastForward !== undefined) {
64
+ panel.dataset.wgFastForward = opts.fastForward ? "1" : "0";
65
+ }
66
+ if (opts.isApi !== undefined) {
67
+ panel.dataset.wgIsApi = opts.isApi ? "1" : "0";
68
+ }
69
+ const buildFfIcon = () => {
70
+ const span = document.createElement("span");
71
+ span.className = "wg-ff-icon";
72
+ span.setAttribute("aria-hidden", "true");
73
+ span.innerHTML =
74
+ '<svg viewBox="0 0 16 16" fill="none">' +
75
+ '<path class="wg-ff-chev" d="M2 3l5 5-5 5" stroke="#c9a6ff" stroke-width="1.8" ' +
76
+ 'stroke-linecap="round" stroke-linejoin="round"/>' +
77
+ '<path class="wg-ff-chev" d="M8 3l5 5-5 5" stroke="#c9a6ff" stroke-width="1.8" ' +
78
+ 'stroke-linecap="round" stroke-linejoin="round"/></svg>';
79
+ return span;
80
+ };
81
+ // Terminal icon: the current step is an API check (defineApiBlock) - no DOM change, no
82
+ // ring of its own, so without this it's an unexplained instant step with nothing visibly
83
+ // happening on the page at all (worse than a fast-forward block, which at least has the
84
+ // FF icon marking it as different).
85
+ const buildApiIcon = () => {
86
+ const span = document.createElement("span");
87
+ span.className = "wg-api-icon";
88
+ span.setAttribute("aria-hidden", "true");
89
+ span.innerHTML =
90
+ '<svg viewBox="0 0 16 16" fill="none">' +
91
+ '<rect x="1" y="2" width="14" height="12" rx="1.5" stroke="#7dd3fc" stroke-width="1.3"/>' +
92
+ '<path d="M3.5 5.5l2.5 2.5-2.5 2.5" stroke="#7dd3fc" stroke-width="1.3" ' +
93
+ 'stroke-linecap="round" stroke-linejoin="round"/>' +
94
+ '<path d="M7.5 10.5h4" stroke="#7dd3fc" stroke-width="1.3" stroke-linecap="round"/></svg>';
95
+ return span;
96
+ };
63
97
  const syncMiniNext = (hidden) => {
64
98
  const miniNext = panel.querySelector("[data-wg-mini-next]");
65
99
  if (!miniNext) return;
@@ -85,10 +119,16 @@ export function installPanelChrome({ title, favicon, bannerPos, todoPos, envAuto
85
119
  const t = panel.querySelector("[data-wg-toggle]");
86
120
  const titleEl = panel.querySelector(".wg-chrome-title");
87
121
  const label = panel.dataset.wgStepLabel || stepLabel;
122
+ const isFf = panel.dataset.wgFastForward === "1";
123
+ const isApi = panel.dataset.wgIsApi === "1";
88
124
  if (titleEl) {
89
- titleEl.textContent = hidden
125
+ const text = hidden
90
126
  ? (label || chromeTitle || "waygraph demo")
91
127
  : (chromeTitle || "waygraph demo");
128
+ titleEl.textContent = "";
129
+ if (hidden && isFf) titleEl.appendChild(buildFfIcon());
130
+ if (hidden && isApi) titleEl.appendChild(buildApiIcon());
131
+ titleEl.appendChild(document.createTextNode(text));
92
132
  }
93
133
  if (t) t.textContent = hidden ? "Show" : "Hide";
94
134
  syncMiniNext(hidden);
@@ -125,7 +125,7 @@ export function installSwipeZoom({ title, favicon, bannerPos, todoPos, envAutopl
125
125
  if (window.__wgSetZoomBadge) window.__wgSetZoomBadge(1, "");
126
126
  };
127
127
  const ZOOM_ICO =
128
- '<svg viewBox="0 0 24 24" fill="none" stroke="#fde68a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
128
+ '<svg viewBox="0 0 24 24" fill="none" stroke="#c9a6ff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
129
129
  '<circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></svg>';
130
130
  window.__wgSetZoomBadge = (scale, sel) => {
131
131
  const n = Number(scale);
@@ -51,7 +51,12 @@ export function installTodos({ title, favicon, bannerPos, todoPos, envAutoplay,
51
51
  );
52
52
  const relayoutTodoDocks = () => {
53
53
  const docks = allDocks();
54
- let top = 72;
54
+ // Must match .wg-todo-dock/#wg-todo-dock's own CSS `top` (runner/overlay-css.js,
55
+ // ui/css/dock.css) - this inline style OVERRIDES that CSS the instant more than one
56
+ // dock exists (multi-todo stacking), so a CSS-only change here is silently underwater;
57
+ // real bug this was: the CSS top was bumped 72 -> 104 for banner clearance, but this
58
+ // hardcoded 72 kept winning at runtime and nothing actually moved.
59
+ let top = 104;
55
60
  for (const el of docks) {
56
61
  el.style.top = top + "px";
57
62
  top += Math.max(48, el.getBoundingClientRect().height) + 10;
@@ -8,7 +8,7 @@ import { isExpectedChainFailure, parseVideoViewport, runChainedFlows, runJsonRep
8
8
  import { runStepMode } from "./step-mode.js";
9
9
  import { connect } from "../types.js";
10
10
  import { MemPage } from "../mem-page.js";
11
- import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../engine.js";
11
+ import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../core.js";
12
12
 
13
13
  async function main() {
14
14
  const projectDir = process.argv[2];
@@ -356,6 +356,13 @@ async function main() {
356
356
  }
357
357
  }
358
358
  } finally {
359
+ // A recorded run's last visible state (a fixture ring, the network panel, a todo dock update)
360
+ // gets cut off mid-fade otherwise - context.close() used to fire the instant the flow's own
361
+ // promise resolved, with zero trailing room. Real, confirmed case: defineApiBlock's network
362
+ // panel only became visible in the recording's final ~1-2s because of this.
363
+ if (process.env.WAYGRAPH_VIDEO && pageForVideo && !pageForVideo.isClosed()) {
364
+ await new Promise((r) => setTimeout(r, 1800));
365
+ }
359
366
  await context.close();
360
367
  const savedVideo =
361
368
  pageForVideo?.video() !== null && pageForVideo?.video() !== undefined
@@ -394,7 +401,7 @@ async function main() {
394
401
 
395
402
  /**
396
403
  * `waygraph run --blocks <flowName> --all-branches`: explore every path through that flow's own
397
- * `.branch()` tree (see src/engine/branch-regression.ts), not just whichever one the live state
404
+ * `.branch()` tree (see src/core/branch-regression.ts), not just whichever one the live state
398
405
  * would dispatch to. Needs a single, bare Flow reference - a multi-segment chain spec has no one
399
406
  * Flow to walk. `--shared-session` opts out of session cloning (WAYGRAPH_SHARED_SESSION=1).
400
407
  */
@@ -0,0 +1,9 @@
1
+ import type { Page } from "@playwright/test";
2
+ import type { NetworkEntry } from "./inpage/network.js";
3
+
4
+ /** Records one network-tab entry (and paints it live) - see network-capture.js's own header. */
5
+ export function recordNetworkEntry(page: Page, entry: NetworkEntry): Promise<void>;
6
+ /** Replays page.__wgNetworkHistory into a freshly (re)installed panel after a navigation. */
7
+ export function restoreNetworkHistory(page: Page): Promise<void>;
8
+ /** Hooks page.on('request'/'requestfinished') to capture real page traffic into the same panel. */
9
+ export function installNetworkCapture(page: Page): void;