waygraph 0.15.47 → 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 (345) 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 +42 -10
  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 +9 -1
  41. package/dist/runner/inpage/banner.js +27 -2
  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/0402cfcf.log +6 -0
  72. package/examples/saucedemo/.waygraph-auto/062b581f.log +20 -0
  73. package/examples/saucedemo/.waygraph-auto/0681582b.log +6 -0
  74. package/examples/saucedemo/.waygraph-auto/07f3e964.log +6 -0
  75. package/examples/saucedemo/.waygraph-auto/0868ae4d.log +0 -0
  76. package/examples/saucedemo/.waygraph-auto/0924ddaa.log +22 -0
  77. package/examples/saucedemo/.waygraph-auto/092d6173.log +5 -0
  78. package/examples/saucedemo/.waygraph-auto/09924510.log +0 -0
  79. package/examples/saucedemo/.waygraph-auto/0998c941.log +21 -0
  80. package/examples/saucedemo/.waygraph-auto/0bf74300.log +21 -0
  81. package/examples/saucedemo/.waygraph-auto/0c01fd29.log +4 -0
  82. package/examples/saucedemo/.waygraph-auto/0c302590.log +0 -0
  83. package/examples/saucedemo/.waygraph-auto/0dee62d6.log +5 -0
  84. package/examples/saucedemo/.waygraph-auto/0eb4c081.log +5 -0
  85. package/examples/saucedemo/.waygraph-auto/10fd431c.log +0 -0
  86. package/examples/saucedemo/.waygraph-auto/13c6fe3c.log +0 -0
  87. package/examples/saucedemo/.waygraph-auto/1581b677.log +0 -0
  88. package/examples/saucedemo/.waygraph-auto/164761a5.log +6 -0
  89. package/examples/saucedemo/.waygraph-auto/1905ceb2.log +0 -0
  90. package/examples/saucedemo/.waygraph-auto/1b1d55c6.log +0 -0
  91. package/examples/saucedemo/.waygraph-auto/1b80fd24.log +6 -0
  92. package/examples/saucedemo/.waygraph-auto/1c30a3c2.log +0 -0
  93. package/examples/saucedemo/.waygraph-auto/1d90aa9a.log +0 -0
  94. package/examples/saucedemo/.waygraph-auto/1de7d889.log +0 -0
  95. package/examples/saucedemo/.waygraph-auto/1f233a4c.log +6 -0
  96. package/examples/saucedemo/.waygraph-auto/20e66801.log +0 -0
  97. package/examples/saucedemo/.waygraph-auto/20ffdb77.log +0 -0
  98. package/examples/saucedemo/.waygraph-auto/22f1a704.log +5 -0
  99. package/examples/saucedemo/.waygraph-auto/239cced3.log +20 -0
  100. package/examples/saucedemo/.waygraph-auto/25204b46.log +4 -0
  101. package/examples/saucedemo/.waygraph-auto/25e2e90f.log +0 -0
  102. package/examples/saucedemo/.waygraph-auto/2708455e.log +22 -0
  103. package/examples/saucedemo/.waygraph-auto/272a96fd.log +20 -0
  104. package/examples/saucedemo/.waygraph-auto/28d7be5d.log +0 -0
  105. package/examples/saucedemo/.waygraph-auto/2a6a8266.log +6 -0
  106. package/examples/saucedemo/.waygraph-auto/2b3401cf.log +20 -0
  107. package/examples/saucedemo/.waygraph-auto/2ceccd6d.log +0 -0
  108. package/examples/saucedemo/.waygraph-auto/2f1b0c13.log +6 -0
  109. package/examples/saucedemo/.waygraph-auto/2f8d4073.log +6 -0
  110. package/examples/saucedemo/.waygraph-auto/30739278.log +6 -0
  111. package/examples/saucedemo/.waygraph-auto/31cb2e80.log +0 -0
  112. package/examples/saucedemo/.waygraph-auto/322d63cd.log +0 -0
  113. package/examples/saucedemo/.waygraph-auto/3239aa8a.log +6 -0
  114. package/examples/saucedemo/.waygraph-auto/326d87b7.log +6 -0
  115. package/examples/saucedemo/.waygraph-auto/3351c0b6.log +0 -0
  116. package/examples/saucedemo/.waygraph-auto/33df0770.log +0 -0
  117. package/examples/saucedemo/.waygraph-auto/340d624d.log +0 -0
  118. package/examples/saucedemo/.waygraph-auto/36367ccf.log +0 -0
  119. package/examples/saucedemo/.waygraph-auto/372536a5.log +6 -0
  120. package/examples/saucedemo/.waygraph-auto/3a412f3c.log +0 -0
  121. package/examples/saucedemo/.waygraph-auto/3a859bd7.log +0 -0
  122. package/examples/saucedemo/.waygraph-auto/3cb0add7.log +0 -0
  123. package/examples/saucedemo/.waygraph-auto/3e42f0d8.log +0 -0
  124. package/examples/saucedemo/.waygraph-auto/4144071d.log +0 -0
  125. package/examples/saucedemo/.waygraph-auto/4176a3c6.log +0 -0
  126. package/examples/saucedemo/.waygraph-auto/41d0793d.log +4 -0
  127. package/examples/saucedemo/.waygraph-auto/424b4d5d.log +0 -0
  128. package/examples/saucedemo/.waygraph-auto/43253aba.log +0 -0
  129. package/examples/saucedemo/.waygraph-auto/438c6c53.log +22 -0
  130. package/examples/saucedemo/.waygraph-auto/4477db12.log +0 -0
  131. package/examples/saucedemo/.waygraph-auto/4a1258b7.log +0 -0
  132. package/examples/saucedemo/.waygraph-auto/4adcd179.log +20 -0
  133. package/examples/saucedemo/.waygraph-auto/4c9d9b16.log +21 -0
  134. package/examples/saucedemo/.waygraph-auto/4da39c36.log +6 -0
  135. package/examples/saucedemo/.waygraph-auto/4dbefa7e.log +5 -0
  136. package/examples/saucedemo/.waygraph-auto/4efa7035.log +6 -0
  137. package/examples/saucedemo/.waygraph-auto/505affdc.log +4 -0
  138. package/examples/saucedemo/.waygraph-auto/51bcb60a.log +0 -0
  139. package/examples/saucedemo/.waygraph-auto/5291bc78.log +22 -0
  140. package/examples/saucedemo/.waygraph-auto/54274c39.log +5 -0
  141. package/examples/saucedemo/.waygraph-auto/5440ce7e.log +0 -0
  142. package/examples/saucedemo/.waygraph-auto/5738175f.log +22 -0
  143. package/examples/saucedemo/.waygraph-auto/57ce5643.log +22 -0
  144. package/examples/saucedemo/.waygraph-auto/5984426b.log +6 -0
  145. package/examples/saucedemo/.waygraph-auto/5a682e7c.log +22 -0
  146. package/examples/saucedemo/.waygraph-auto/5b79320c.log +21 -0
  147. package/examples/saucedemo/.waygraph-auto/5c55aaac.log +21 -0
  148. package/examples/saucedemo/.waygraph-auto/5ed00b16.log +4 -0
  149. package/examples/saucedemo/.waygraph-auto/60b9c066.log +6 -0
  150. package/examples/saucedemo/.waygraph-auto/610dd127.log +0 -0
  151. package/examples/saucedemo/.waygraph-auto/61105500.log +5 -0
  152. package/examples/saucedemo/.waygraph-auto/6134afe8.log +20 -0
  153. package/examples/saucedemo/.waygraph-auto/62a0bdc9.log +22 -0
  154. package/examples/saucedemo/.waygraph-auto/6376fc15.log +0 -0
  155. package/examples/saucedemo/.waygraph-auto/6599cbca.log +22 -0
  156. package/examples/saucedemo/.waygraph-auto/67aaca30.log +0 -0
  157. package/examples/saucedemo/.waygraph-auto/68b10298.log +0 -0
  158. package/examples/saucedemo/.waygraph-auto/68be5e12.log +0 -0
  159. package/examples/saucedemo/.waygraph-auto/68df05a6.log +22 -0
  160. package/examples/saucedemo/.waygraph-auto/693f67c4.log +20 -0
  161. package/examples/saucedemo/.waygraph-auto/69ae030a.log +6 -0
  162. package/examples/saucedemo/.waygraph-auto/69e73f35.log +6 -0
  163. package/examples/saucedemo/.waygraph-auto/6b2333b0.log +5 -0
  164. package/examples/saucedemo/.waygraph-auto/6c4c3817.log +0 -0
  165. package/examples/saucedemo/.waygraph-auto/6c954911.log +0 -0
  166. package/examples/saucedemo/.waygraph-auto/6d65a439.log +5 -0
  167. package/examples/saucedemo/.waygraph-auto/6d700055.log +0 -0
  168. package/examples/saucedemo/.waygraph-auto/6ead848f.log +0 -0
  169. package/examples/saucedemo/.waygraph-auto/72675b2d.log +6 -0
  170. package/examples/saucedemo/.waygraph-auto/733dd260.log +5 -0
  171. package/examples/saucedemo/.waygraph-auto/75016486.log +0 -0
  172. package/examples/saucedemo/.waygraph-auto/752b01c6.log +22 -0
  173. package/examples/saucedemo/.waygraph-auto/75675227.log +6 -0
  174. package/examples/saucedemo/.waygraph-auto/75e2e658.log +0 -0
  175. package/examples/saucedemo/.waygraph-auto/76ac1a86.log +0 -0
  176. package/examples/saucedemo/.waygraph-auto/77605295.log +0 -0
  177. package/examples/saucedemo/.waygraph-auto/792671f4.log +22 -0
  178. package/examples/saucedemo/.waygraph-auto/79915adb.log +20 -0
  179. package/examples/saucedemo/.waygraph-auto/7a398774.log +6 -0
  180. package/examples/saucedemo/.waygraph-auto/7a72f66e.log +6 -0
  181. package/examples/saucedemo/.waygraph-auto/7a984334.log +4 -0
  182. package/examples/saucedemo/.waygraph-auto/7c6ee793.log +20 -0
  183. package/examples/saucedemo/.waygraph-auto/7c726dc4.log +22 -0
  184. package/examples/saucedemo/.waygraph-auto/7c72e8a5.log +4 -0
  185. package/examples/saucedemo/.waygraph-auto/7dbee625.log +22 -0
  186. package/examples/saucedemo/.waygraph-auto/7df66956.log +0 -0
  187. package/examples/saucedemo/.waygraph-auto/7e053160.log +0 -0
  188. package/examples/saucedemo/.waygraph-auto/802a0b5b.log +0 -0
  189. package/examples/saucedemo/.waygraph-auto/80322e0b.log +0 -0
  190. package/examples/saucedemo/.waygraph-auto/80a4978e.log +6 -0
  191. package/examples/saucedemo/.waygraph-auto/81cfe480.log +22 -0
  192. package/examples/saucedemo/.waygraph-auto/832f5add.log +0 -0
  193. package/examples/saucedemo/.waygraph-auto/8337b6ad.log +0 -0
  194. package/examples/saucedemo/.waygraph-auto/8493928e.log +0 -0
  195. package/examples/saucedemo/.waygraph-auto/853bde43.log +0 -0
  196. package/examples/saucedemo/.waygraph-auto/86350ea6.log +22 -0
  197. package/examples/saucedemo/.waygraph-auto/86bb598a.log +0 -0
  198. package/examples/saucedemo/.waygraph-auto/86d09876.log +22 -0
  199. package/examples/saucedemo/.waygraph-auto/878ad01b.log +4 -0
  200. package/examples/saucedemo/.waygraph-auto/87c88ba5.log +0 -0
  201. package/examples/saucedemo/.waygraph-auto/87cb80ff.log +0 -0
  202. package/examples/saucedemo/.waygraph-auto/880b2e78.log +6 -0
  203. package/examples/saucedemo/.waygraph-auto/88527936.log +5 -0
  204. package/examples/saucedemo/.waygraph-auto/893023ea.log +5 -0
  205. package/examples/saucedemo/.waygraph-auto/89416718.log +0 -0
  206. package/examples/saucedemo/.waygraph-auto/8996a857.log +6 -0
  207. package/examples/saucedemo/.waygraph-auto/8a64ba0f.log +6 -0
  208. package/examples/saucedemo/.waygraph-auto/8b1cc2aa.log +6 -0
  209. package/examples/saucedemo/.waygraph-auto/8b73d13e.log +6 -0
  210. package/examples/saucedemo/.waygraph-auto/8d9e5cd2.log +21 -0
  211. package/examples/saucedemo/.waygraph-auto/8ec7d260.log +0 -0
  212. package/examples/saucedemo/.waygraph-auto/8ed43279.log +0 -0
  213. package/examples/saucedemo/.waygraph-auto/93acae32.log +5 -0
  214. package/examples/saucedemo/.waygraph-auto/96321a08.log +0 -0
  215. package/examples/saucedemo/.waygraph-auto/9742b6c2.log +6 -0
  216. package/examples/saucedemo/.waygraph-auto/99cc93eb.log +6 -0
  217. package/examples/saucedemo/.waygraph-auto/9cbfbedc.log +0 -0
  218. package/examples/saucedemo/.waygraph-auto/9dc147d2.log +22 -0
  219. package/examples/saucedemo/.waygraph-auto/a215a395.log +22 -0
  220. package/examples/saucedemo/.waygraph-auto/a23b7086.log +4 -0
  221. package/examples/saucedemo/.waygraph-auto/a35bd5ec.log +0 -0
  222. package/examples/saucedemo/.waygraph-auto/a68995e9.log +22 -0
  223. package/examples/saucedemo/.waygraph-auto/a6e4f936.log +22 -0
  224. package/examples/saucedemo/.waygraph-auto/a7da862b.log +0 -0
  225. package/examples/saucedemo/.waygraph-auto/a82e2a48.log +0 -0
  226. package/examples/saucedemo/.waygraph-auto/a952eb91.log +0 -0
  227. package/examples/saucedemo/.waygraph-auto/a9559653.log +5 -0
  228. package/examples/saucedemo/.waygraph-auto/aa478de2.log +0 -0
  229. package/examples/saucedemo/.waygraph-auto/ac350fc7.log +20 -0
  230. package/examples/saucedemo/.waygraph-auto/acc1b63a.log +0 -0
  231. package/examples/saucedemo/.waygraph-auto/ad12d191.log +0 -0
  232. package/examples/saucedemo/.waygraph-auto/b04638f4.log +6 -0
  233. package/examples/saucedemo/.waygraph-auto/b48863e5.log +22 -0
  234. package/examples/saucedemo/.waygraph-auto/b56968e1.log +6 -0
  235. package/examples/saucedemo/.waygraph-auto/b64e0620.log +20 -0
  236. package/examples/saucedemo/.waygraph-auto/b86a6218.log +6 -0
  237. package/examples/saucedemo/.waygraph-auto/b8e9e956.log +22 -0
  238. package/examples/saucedemo/.waygraph-auto/b9b310ff.log +21 -0
  239. package/examples/saucedemo/.waygraph-auto/bc111745.log +22 -0
  240. package/examples/saucedemo/.waygraph-auto/bf7a77a2.log +0 -0
  241. package/examples/saucedemo/.waygraph-auto/c0d6f353.log +21 -0
  242. package/examples/saucedemo/.waygraph-auto/c0febcf2.log +20 -0
  243. package/examples/saucedemo/.waygraph-auto/c4c52998.log +6 -0
  244. package/examples/saucedemo/.waygraph-auto/c809ceb4.log +22 -0
  245. package/examples/saucedemo/.waygraph-auto/ca6de7e7.log +0 -0
  246. package/examples/saucedemo/.waygraph-auto/ca8561bc.log +0 -0
  247. package/examples/saucedemo/.waygraph-auto/cb86d45b.log +0 -0
  248. package/examples/saucedemo/.waygraph-auto/cb9a1978.log +6 -0
  249. package/examples/saucedemo/.waygraph-auto/cbbc689c.log +6 -0
  250. package/examples/saucedemo/.waygraph-auto/cd88364b.log +0 -0
  251. package/examples/saucedemo/.waygraph-auto/cd919e1d.log +0 -0
  252. package/examples/saucedemo/.waygraph-auto/cfff9eef.log +20 -0
  253. package/examples/saucedemo/.waygraph-auto/d0f59b21.log +4 -0
  254. package/examples/saucedemo/.waygraph-auto/d1195079.log +20 -0
  255. package/examples/saucedemo/.waygraph-auto/d2ef067a.log +5 -0
  256. package/examples/saucedemo/.waygraph-auto/d425471f.log +6 -0
  257. package/examples/saucedemo/.waygraph-auto/d5293921.log +0 -0
  258. package/examples/saucedemo/.waygraph-auto/d62a22c2.log +21 -0
  259. package/examples/saucedemo/.waygraph-auto/d6d1761f.log +22 -0
  260. package/examples/saucedemo/.waygraph-auto/d6d5f411.log +22 -0
  261. package/examples/saucedemo/.waygraph-auto/d6df2771.log +6 -0
  262. package/examples/saucedemo/.waygraph-auto/d7075012.log +21 -0
  263. package/examples/saucedemo/.waygraph-auto/d9ddc297.log +0 -0
  264. package/examples/saucedemo/.waygraph-auto/db4ac845.log +0 -0
  265. package/examples/saucedemo/.waygraph-auto/db6d7774.log +0 -0
  266. package/examples/saucedemo/.waygraph-auto/db839827.log +5 -0
  267. package/examples/saucedemo/.waygraph-auto/dde5e859.log +22 -0
  268. package/examples/saucedemo/.waygraph-auto/de8cac58.log +0 -0
  269. package/examples/saucedemo/.waygraph-auto/dedfcb18.log +0 -0
  270. package/examples/saucedemo/.waygraph-auto/def4d9b1.log +0 -0
  271. package/examples/saucedemo/.waygraph-auto/e1549e40.log +0 -0
  272. package/examples/saucedemo/.waygraph-auto/e1b0676d.log +21 -0
  273. package/examples/saucedemo/.waygraph-auto/e5111463.log +0 -0
  274. package/examples/saucedemo/.waygraph-auto/e5fc1d7c.log +5 -0
  275. package/examples/saucedemo/.waygraph-auto/e6fd2202.log +0 -0
  276. package/examples/saucedemo/.waygraph-auto/edaa806d.log +0 -0
  277. package/examples/saucedemo/.waygraph-auto/edaf33de.log +0 -0
  278. package/examples/saucedemo/.waygraph-auto/edd40cbb.log +20 -0
  279. package/examples/saucedemo/.waygraph-auto/eddfbffc.log +6 -0
  280. package/examples/saucedemo/.waygraph-auto/ee9fa1ad.log +5 -0
  281. package/examples/saucedemo/.waygraph-auto/ef319474.log +22 -0
  282. package/examples/saucedemo/.waygraph-auto/f28eee8d.log +0 -0
  283. package/examples/saucedemo/.waygraph-auto/f33bde90.log +0 -0
  284. package/examples/saucedemo/.waygraph-auto/f6ba7cb4.log +6 -0
  285. package/examples/saucedemo/.waygraph-auto/f7ac4d62.log +20 -0
  286. package/examples/saucedemo/.waygraph-auto/f929bb79.log +0 -0
  287. package/examples/saucedemo/.waygraph-auto/f92d4c6c.log +22 -0
  288. package/examples/saucedemo/.waygraph-auto/f92faf40.log +5 -0
  289. package/examples/saucedemo/.waygraph-auto/fa784369.log +21 -0
  290. package/examples/saucedemo/.waygraph-auto/fb55f723.log +20 -0
  291. package/examples/saucedemo/.waygraph-auto/fba3b738.log +0 -0
  292. package/examples/saucedemo/.waygraph-auto/ffdf2854.log +6 -0
  293. package/examples/saucedemo/README.md +13 -2
  294. package/examples/saucedemo/package.json +4 -0
  295. package/examples/saucedemo/src/flows/api-demo.flow.ts +37 -0
  296. package/examples/saucedemo/src/flows/checkout.flow.ts +34 -11
  297. package/package.json +5 -3
  298. package/dist/auto-explore-run.d.ts +0 -37
  299. package/dist/auto-explore-run.js +0 -670
  300. package/dist/auto-explore.d.ts +0 -57
  301. package/dist/auto-explore.js +0 -376
  302. package/dist/auto-session-ipc.d.ts +0 -150
  303. package/dist/auto-session-ipc.js +0 -497
  304. package/dist/block-inject.d.ts +0 -15
  305. package/dist/block-inject.js +0 -91
  306. package/dist/browser.d.ts +0 -15
  307. package/dist/browser.js +0 -29
  308. package/dist/coverage-gap.d.ts +0 -11
  309. package/dist/coverage-gap.js +0 -119
  310. package/dist/engine.d.ts +0 -12
  311. package/dist/engine.js +0 -13
  312. package/dist/graph.d.ts +0 -92
  313. package/dist/graph.js +0 -467
  314. package/dist/highlight-shorthand.d.ts +0 -24
  315. package/dist/highlight-shorthand.js +0 -30
  316. package/dist/map-check.d.ts +0 -18
  317. package/dist/map-check.js +0 -140
  318. package/dist/overlay-beacon.d.ts +0 -44
  319. package/dist/overlay-beacon.js +0 -85
  320. package/dist/pilot.d.ts +0 -54
  321. package/dist/pilot.js +0 -80
  322. package/dist/practices-check.d.ts +0 -14
  323. package/dist/practices-check.js +0 -195
  324. package/dist/traverse-coverage.d.ts +0 -59
  325. package/dist/traverse-coverage.js +0 -127
  326. package/dist/traverse-lease.d.ts +0 -18
  327. package/dist/traverse-lease.js +0 -62
  328. package/dist/traverse-run.d.ts +0 -47
  329. package/dist/traverse-run.js +0 -439
  330. package/dist/ui/compose.d.ts +0 -4
  331. package/dist/ui/compose.js +0 -7
  332. /package/dist/{verbose-log.d.ts → auto-session/verbose-log.d.ts} +0 -0
  333. /package/dist/{verbose-log.js → auto-session/verbose-log.js} +0 -0
  334. /package/dist/{agent-dive.d.ts → commands/agent-dive-scaffold.d.ts} +0 -0
  335. /package/dist/{engine/core.d.ts → core/block.d.ts} +0 -0
  336. /package/dist/{engine → core}/blocks/nav.d.ts +0 -0
  337. /package/dist/{engine → core}/blocks/page.d.ts +0 -0
  338. /package/dist/{engine → core}/branch-regression.d.ts +0 -0
  339. /package/dist/{engine → core}/compose.d.ts +0 -0
  340. /package/dist/{engine → core}/config.d.ts +0 -0
  341. /package/dist/{engine → core}/config.js +0 -0
  342. /package/dist/{engine → core}/flow.d.ts +0 -0
  343. /package/dist/{engine → core}/locate.d.ts +0 -0
  344. /package/dist/{engine → core}/locate.js +0 -0
  345. /package/dist/{engine → core}/run-graph.d.ts +0 -0
@@ -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;
@@ -0,0 +1,126 @@
1
+ // Real page network traffic -> the same network-tab overlay defineApiBlock's own calls use (see
2
+ // inpage/network.js's own header). Playwright's page.on('request'/'requestfinished') events cover
3
+ // every real request the PAGE makes (XHR/fetch/navigation) - not page.request.get()-style calls,
4
+ // which go through a separate APIRequestContext entirely and never touch the browser at all (that
5
+ // side is covered by defineApiBlock's own explicit call, in src/core/blocks/api.ts).
6
+ import { addNetworkEntry, clearNetworkLog } from "./inpage/network.js";
7
+
8
+ // Fetch/XHR/navigation only - a real page can fire dozens of image/font/stylesheet requests per
9
+ // second, which would flood a panel meant to answer "what API calls did this page just made".
10
+ const RELEVANT_TYPES = new Set(["xhr", "fetch", "document"]);
11
+ // Response bodies this size or smaller, and only if they look text-ish, get captured for the
12
+ // detail view - a multi-MB image/video response has no business being buffered into page memory
13
+ // just because a demo happened to be running.
14
+ const MAX_BODY_BYTES = 200_000;
15
+ // Matches the in-page addNetworkEntry's own cap (network.js) - the Node-side history this backs
16
+ // stays in sync with what the panel can actually show.
17
+ const MAX_HISTORY = 30;
18
+
19
+ /**
20
+ * Records one entry AND paints it live - the single place that touches page.__wgNetworkHistory,
21
+ * so every caller (this file's own listeners, defineApiBlock) stays in sync automatically. History
22
+ * lives on the Playwright `Page` object (Node side), which survives navigation - the panel DOM
23
+ * (page side, inside the shadow root) does not, and gets wiped on every real navigation. Without
24
+ * this, the "network tab" reset to empty on every step that navigated - not what a persistent
25
+ * Network tab is supposed to do.
26
+ */
27
+ export function recordNetworkEntry(page, entry) {
28
+ page.__wgNetworkHistory = page.__wgNetworkHistory || [];
29
+ page.__wgNetworkHistory.push(entry);
30
+ while (page.__wgNetworkHistory.length > MAX_HISTORY) page.__wgNetworkHistory.shift();
31
+ return page.evaluate(addNetworkEntry, entry).catch(() => {});
32
+ }
33
+
34
+ /**
35
+ * Replays whatever history survived the last navigation back into a freshly (re)installed panel -
36
+ * call this after ensureShadowRoot, every step, same as the rest of the overlay's own per-step
37
+ * resync (banner/todos/device), and BEFORE that step's own network activity can add anything new
38
+ * (installOverlay runs at the very start of a step, so this is always true in practice - no
39
+ * interleaving race between "replay old" and "record new" to reason about). A no-op when there's
40
+ * no history yet, or the panel already shows exactly as many entries as history has (nothing was
41
+ * wiped this step). Otherwise clears and rebuilds from scratch, in order - simpler and more
42
+ * obviously correct than trying to diff/append just the "missing" ones.
43
+ */
44
+ export async function restoreNetworkHistory(page) {
45
+ const history = page.__wgNetworkHistory;
46
+ if (!history || history.length === 0) return;
47
+ // page.__wgNetworkNeedsRestore is set by installNetworkCapture's own framenavigated listener -
48
+ // skip the page.evaluate() round-trip entirely (an extra one on EVERY step otherwise, since this
49
+ // runs from installOverlay every step) unless a real navigation actually happened since the last
50
+ // successful restore. A real, caught perf regression: this used to always evaluate() a shown-count
51
+ // check first, which measurably slowed down every step of every test that had ever captured any
52
+ // traffic at all, not just ones that navigate.
53
+ if (!page.__wgNetworkNeedsRestore) return;
54
+ page.__wgNetworkNeedsRestore = false;
55
+ await page.evaluate(clearNetworkLog).catch(() => {});
56
+ for (const entry of history) {
57
+ await page.evaluate(addNetworkEntry, entry).catch(() => {});
58
+ }
59
+ }
60
+
61
+ export function installNetworkCapture(page) {
62
+ if (page.__wgNetworkCaptureInstalled) return;
63
+ page.__wgNetworkCaptureInstalled = true;
64
+
65
+ // Marks history as needing a replay - see restoreNetworkHistory's own comment. Main frame only;
66
+ // an iframe navigating doesn't wipe the top-level shadow root the panel lives in.
67
+ page.on("framenavigated", (frame) => {
68
+ if (frame === page.mainFrame()) page.__wgNetworkNeedsRestore = true;
69
+ });
70
+
71
+ const startedAt = new Map();
72
+
73
+ page.on("request", (request) => {
74
+ startedAt.set(request, Date.now());
75
+ });
76
+
77
+ page.on("requestfinished", async (request) => {
78
+ try {
79
+ if (!RELEVANT_TYPES.has(request.resourceType())) return;
80
+ const response = await request.response();
81
+ if (!response) return;
82
+ const start = startedAt.get(request);
83
+ startedAt.delete(request);
84
+ let resBody;
85
+ try {
86
+ const contentType = (await response.headerValue("content-type")) || "";
87
+ if (/json|text|xml|html|javascript/.test(contentType)) {
88
+ const buf = await response.body();
89
+ if (buf.length <= MAX_BODY_BYTES) resBody = buf.toString("utf8");
90
+ }
91
+ } catch {
92
+ /* body already consumed / redirected away / not available - best-effort only */
93
+ }
94
+ const [reqHeaders, resHeaders] = await Promise.all([
95
+ request.allHeaders().catch(() => undefined),
96
+ response.allHeaders().catch(() => undefined),
97
+ ]);
98
+ await recordNetworkEntry(page, {
99
+ method: request.method(),
100
+ url: request.url(),
101
+ status: response.status(),
102
+ ok: response.ok(),
103
+ ms: start !== undefined ? Date.now() - start : undefined,
104
+ reqHeaders,
105
+ resHeaders,
106
+ reqBody: request.postData() || undefined,
107
+ resBody,
108
+ });
109
+ } catch {
110
+ /* a capture failure must never break the actual run it's observing */
111
+ }
112
+ });
113
+
114
+ page.on("requestfailed", (request) => {
115
+ startedAt.delete(request);
116
+ if (!RELEVANT_TYPES.has(request.resourceType())) return;
117
+ recordNetworkEntry(page, {
118
+ method: request.method(),
119
+ url: request.url(),
120
+ status: 0,
121
+ ok: false,
122
+ reqBody: request.postData() || undefined,
123
+ resBody: request.failure() ? request.failure().errorText : undefined,
124
+ });
125
+ });
126
+ }
@@ -80,7 +80,7 @@ export const RUNNER_EXTRA_CSS =
80
80
  // Todo checklist(s) float outside #wg-panel so --mini / Hide never hide them.
81
81
  // Multiple docks (one per todoId) are supported - stacked on the same side.
82
82
  // Click a dock to slide left <-> right (WAYGRAPH_TODO_POS / --todo-left|right).
83
- ".wg-todo-dock,#wg-todo-dock{position:fixed;z-index:2147483646;top:72px;left:14px;" +
83
+ ".wg-todo-dock,#wg-todo-dock{position:fixed;z-index:2147483646;top:104px;left:14px;" +
84
84
  "width:min(280px,42vw);max-height:calc(100vh - 100px);overflow:auto;box-sizing:border-box;" +
85
85
  "padding:10px 12px;background:" + SURFACE + ";color:#fff;border-radius:12px;" +
86
86
  "border:1px solid rgba(124,58,237,.45);box-shadow:0 8px 24px rgba(0,0,0,.35);" +
@@ -102,18 +102,74 @@ export const RUNNER_EXTRA_CSS =
102
102
  ".wg-todo-dock .wg-todo-dock-title{font:700 11px/1.2 system-ui,sans-serif;color:#c9a6ff;" +
103
103
  "letter-spacing:.04em;text-transform:uppercase;margin:0 0 8px;}" +
104
104
  ".wg-todo-dock .wg-todos-list,#wg-todo-dock #wg-todos,.wg-todo-dock #wg-todos{list-style:none;margin:0;padding:0;background:transparent;border:none;}" +
105
- // Always-on zoom HUD - bottom-right (top-left is crowded: todos + banners).
105
+ // Always-on zoom HUD - bottom-right (top-left is crowded: todos + banners). Violet, matching the
106
+ // rest of the overlay's design tokens - this used to be a lone amber/yellow badge, the one
107
+ // surface that never got pulled into the shared palette when everything else did.
106
108
  "#wg-zoom-badge{position:fixed;z-index:2147483646;bottom:14px;right:14px;" +
107
109
  "display:flex;align-items:center;gap:7px;padding:6px 11px 6px 8px;" +
108
110
  "border-radius:999px;background:" + SURFACE + ";color:#f0e8ff;" +
109
- "border:1px solid rgba(250,204,21,.6);box-shadow:0 6px 18px rgba(0,0,0,.4);" +
111
+ "border:1px solid rgba(124,58,237,.55);box-shadow:0 6px 18px rgba(0,0,0,.4);" +
110
112
  "font:700 12px/1.2 system-ui,sans-serif;pointer-events:none;" +
111
113
  "opacity:1;transform:translateY(0);}" +
112
114
  "#wg-zoom-badge .wg-zoom-ico{width:18px;height:18px;display:flex;align-items:center;justify-content:center;" +
113
- "border-radius:6px;background:rgba(250,204,21,.22);}" +
115
+ "border-radius:6px;background:rgba(124,58,237,.28);}" +
114
116
  "#wg-zoom-badge .wg-zoom-ico svg{width:14px;height:14px;display:block;}" +
115
- "#wg-zoom-badge .wg-zoom-val{color:#fde68a;font-variant-numeric:tabular-nums;font-weight:800;min-width:3.2em;}" +
116
- "#wg-zoom-badge[data-zoomed=\"1\"]{border-color:#fbbf24;}" +
117
+ "#wg-zoom-badge .wg-zoom-val{color:#c9a6ff;font-variant-numeric:tabular-nums;font-weight:800;min-width:3.2em;}" +
118
+ "#wg-zoom-badge[data-zoomed=\"1\"]{border-color:#7C3AED;}" +
119
+ // Network-tab overlay (real page traffic via network-capture.js + defineApiBlock's own
120
+ // page.request calls) - bottom-left, the one corner free of the zoom HUD (bottom-right) and the
121
+ // typing chip (bottom-center). Persistent (does not auto-fade) once any entry exists - this is a
122
+ // real Postman/DevTools-style inspector meant to be reviewed, not a flash-and-gone toast.
123
+ "#wg-network-log{position:fixed;z-index:2147483646;bottom:14px;left:14px;min-width:260px;" +
124
+ "max-width:min(92vw,420px);max-height:min(60vh,420px);display:flex;flex-direction:column;" +
125
+ "border-radius:10px;background:" + SURFACE + ";color:#f0e8ff;border:1px solid rgba(124,58,237,.45);" +
126
+ "box-shadow:0 8px 22px rgba(0,0,0,.4);font:12px/1.4 ui-monospace,\"SF Mono\",Consolas,monospace;" +
127
+ "opacity:0;transform:translateY(8px);transition:opacity .25s ease,transform .25s ease;overflow:hidden;}" +
128
+ "#wg-network-log.wg-in{opacity:1;transform:translateY(0);}" +
129
+ "#wg-network-log.wg-net-collapsed .wg-net-list{display:none;}" +
130
+ "#wg-network-log .wg-net-header{display:flex;align-items:center;gap:6px;padding:8px 10px;" +
131
+ "border-bottom:1px solid rgba(124,58,237,.25);cursor:default;flex:0 0 auto;}" +
132
+ "#wg-network-log .wg-net-title{font:700 10px/1.2 system-ui,sans-serif;color:#c9a6ff;" +
133
+ "letter-spacing:.06em;text-transform:uppercase;flex:1 1 auto;}" +
134
+ "#wg-network-log .wg-net-count{font:700 10px/1.2 system-ui,sans-serif;color:#9CA3AF;" +
135
+ "background:rgba(124,58,237,.22);border-radius:999px;padding:1px 7px;}" +
136
+ "#wg-network-log .wg-net-collapse{flex:0 0 auto;width:18px;height:18px;border-radius:5px;border:none;" +
137
+ "background:rgba(124,58,237,.28);color:#e8dcff;font:700 13px/1 system-ui,sans-serif;cursor:pointer;" +
138
+ "pointer-events:auto;}" +
139
+ "#wg-network-log .wg-net-collapse:hover{background:rgba(124,58,237,.42);}" +
140
+ "#wg-network-log .wg-net-list{list-style:none;margin:0;padding:6px 8px;display:flex;" +
141
+ "flex-direction:column;gap:2px;overflow-y:auto;pointer-events:auto;}" +
142
+ "#wg-network-log .wg-net-row{display:flex;align-items:baseline;gap:7px;opacity:0;padding:3px 4px;" +
143
+ "border-radius:5px;cursor:pointer;transform:translateX(-4px);transition:opacity .2s ease,transform .2s ease;}" +
144
+ "#wg-network-log .wg-net-row:hover,#wg-network-log .wg-net-row.wg-net-open{background:rgba(124,58,237,.18);}" +
145
+ "#wg-network-log .wg-net-row.wg-in{opacity:1;transform:translateX(0);}" +
146
+ "#wg-network-log .wg-net-method{flex:0 0 auto;font-weight:800;font-size:10px;min-width:38px;}" +
147
+ "#wg-network-log .wg-net-method-get{color:#3B82F6;}" +
148
+ "#wg-network-log .wg-net-method-post{color:#22C55E;}" +
149
+ "#wg-network-log .wg-net-method-put{color:#F97316;}" +
150
+ "#wg-network-log .wg-net-method-delete{color:#EF4444;}" +
151
+ "#wg-network-log .wg-net-method-other{color:#9CA3AF;}" +
152
+ "#wg-network-log .wg-net-path{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;" +
153
+ "white-space:nowrap;color:#e0e0f0;}" +
154
+ "#wg-network-log .wg-net-status{flex:0 0 auto;font-weight:700;color:#22C55E;}" +
155
+ "#wg-network-log .wg-net-row[data-ok=\"0\"] .wg-net-status{color:#EF4444;}" +
156
+ "#wg-network-log .wg-net-ms{flex:0 0 auto;color:#9CA3AF;font-size:10px;}" +
157
+ "#wg-network-log .wg-net-detail{list-style:none;background:rgba(0,0,0,.28);border-radius:6px;" +
158
+ "padding:8px;margin:2px 0 6px;}" +
159
+ "#wg-network-log .wg-net-detail-section{margin-bottom:8px;}" +
160
+ "#wg-network-log .wg-net-detail-section:last-child{margin-bottom:0;}" +
161
+ "#wg-network-log .wg-net-detail-section h4{margin:0 0 4px;font:700 9px/1.2 system-ui,sans-serif;" +
162
+ "color:#9CA3AF;letter-spacing:.06em;text-transform:uppercase;}" +
163
+ "#wg-network-log .wg-net-headers{width:100%;border-collapse:collapse;font-size:11px;}" +
164
+ "#wg-network-log .wg-net-headers td{padding:1px 6px 1px 0;vertical-align:top;word-break:break-all;}" +
165
+ "#wg-network-log .wg-net-headers td:first-child{color:#c9a6ff;white-space:nowrap;}" +
166
+ "#wg-network-log .wg-net-body{margin:0;font-size:11px;white-space:pre-wrap;word-break:break-all;" +
167
+ "max-height:160px;overflow-y:auto;color:#e0e0f0;}" +
168
+ "#wg-network-log .wg-net-curl{color:#7dd3fc;}" +
169
+ "#wg-network-log .wg-net-empty{font-size:11px;color:#6b7280;font-style:italic;}" +
170
+ "#wg-network-log .wg-net-copy{margin-top:5px;padding:3px 9px;border-radius:5px;border:1px solid rgba(124,58,237,.5);" +
171
+ "background:rgba(124,58,237,.22);color:#e8dcff;font:700 10px system-ui,sans-serif;cursor:pointer;}" +
172
+ "#wg-network-log .wg-net-copy:hover{background:rgba(124,58,237,.38);}" +
117
173
  // Typing chip (method fills: username / password / etc.)
118
174
  "#wg-typing-badge{position:fixed;z-index:2147483646;bottom:88px;left:50%;transform:translateX(-50%);" +
119
175
  "display:flex;align-items:center;gap:8px;padding:8px 14px;" +
@@ -254,7 +310,15 @@ export const RUNNER_EXTRA_CSS =
254
310
  // Hide / Show chrome: collapsed = compact "N / M · block" pill + Next (manual).
255
311
  "#wg-panel .wg-chrome{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:0 0 8px;}" +
256
312
  "#wg-panel .wg-chrome-title{font:700 11px/1.2 system-ui,sans-serif;color:#c9a6ff;" +
257
- "letter-spacing:.04em;text-transform:uppercase;flex:1;min-width:0;}" +
313
+ "letter-spacing:.04em;text-transform:uppercase;flex:1;min-width:0;display:flex;align-items:center;gap:4px;}" +
314
+ // Animated fast-forward indicator on the collapsed bottom-center pill - a blitzed/FF step has
315
+ // no ring, no narration theater, nothing else visible marking it as different, so it read as
316
+ // just another normal step with no explanation for why it snapped past instantly.
317
+ "#wg-panel .wg-ff-icon{display:inline-flex;align-items:center;flex-shrink:0;width:13px;height:13px;}" +
318
+ "#wg-panel .wg-ff-icon svg{width:100%;height:100%;display:block;}" +
319
+ "#wg-panel .wg-ff-icon .wg-ff-chev{animation:wg-ff-pulse 900ms ease-in-out infinite;}" +
320
+ "#wg-panel .wg-ff-icon .wg-ff-chev:nth-child(2){animation-delay:150ms;}" +
321
+ "@keyframes wg-ff-pulse{0%,100%{opacity:.3;transform:translateX(-1.5px);}50%{opacity:1;transform:translateX(1.5px);}}" +
258
322
  "#wg-panel .wg-chrome-actions{display:flex;align-items:center;gap:6px;flex-shrink:0;}" +
259
323
  "#wg-panel button.wg-hide-btn,#wg-panel button.wg-mini-next{margin:0;padding:4px 10px;font:600 11px system-ui,sans-serif;" +
260
324
  "background:#3a2a60;color:#e8dcff;border:1px solid #5b3aa8;border-radius:6px;cursor:pointer;}" +
@@ -6,16 +6,46 @@ import { resolveTodoDockUi } from "../highlights.js";
6
6
  import { installCore } from "./inpage/core.js";
7
7
  import { installSwipeZoom } from "./inpage/swipe-zoom.js";
8
8
  import { installBanner } from "./inpage/banner.js";
9
+ import { showCaption, hideCaption } from "./inpage/caption.js";
9
10
  import { installStamp } from "./inpage/stamp.js";
10
11
  import { installPanelChrome } from "./inpage/panel-chrome.js";
11
12
  import { installTodos } from "./inpage/todos.js";
12
13
  import { installDevice } from "./inpage/device.js";
13
14
  import { applyVideoDeviceStage } from "./device-stage.js";
15
+ import { installNetworkCapture, restoreNetworkHistory } from "./network-capture.js";
16
+ import { setNetworkTabVisible } from "./inpage/network.js";
14
17
 
15
- /** `ui` = authored banner UX from the stub phase: { pos, collision, hidden } (all optional). */
16
- export async function installOverlay(page, title, ui) {
18
+ /**
19
+ * `ui` = authored banner UX from the stub phase: { pos, collision, hidden } (all optional).
20
+ * `caption` = bottom subtitle-bar text (ctx.caption()/ctx.hideCaption()) - `undefined` leaves it
21
+ * alone (unset this step), `""` hides it, any other string shows/updates it.
22
+ * `networkTabVisible` = network-tab panel shown/hidden (ctx.showNetworkTab()/hideNetworkTab()) -
23
+ * `undefined` leaves it alone (default state is hidden, set the very first time restoreNetworkHistory
24
+ * builds a panel); capture itself is unconditional and unaffected by this either way.
25
+ */
26
+ export async function installOverlay(page, title, ui, caption, networkTabVisible) {
17
27
  // ring/cursor/banner/dock come from the ONE shared bundle every surface installs (ui/css/*.css).
18
28
  await ensureShadowRoot(page);
29
+ // Idempotent (guarded on page.__wgNetworkCaptureInstalled) - safe to call every step even though
30
+ // installOverlay itself runs every step; the page.on() listeners this installs are attached to
31
+ // the Page object, not any one document, so they already survive navigations on their own.
32
+ installNetworkCapture(page);
33
+ // Visibility is Node-side state too (page.__wgNetworkTabVisible), same reason history is: a
34
+ // navigation wipes window.__wgNetworkTabVisible along with the rest of the page-side JS state,
35
+ // so "shown" would silently revert to the hidden default on the very next navigated step without
36
+ // this. Default false (hidden) - matches addNetworkEntry's own default-hidden behavior.
37
+ if (networkTabVisible !== undefined) page.__wgNetworkTabVisible = !!networkTabVisible;
38
+ await page.evaluate((v) => { window.__wgNetworkTabVisible = v; }, !!page.__wgNetworkTabVisible).catch(() => {});
39
+ // Real bug this fixes: a navigation wipes the shadow root (and with it, the network panel's DOM
40
+ // and in-page entry list) - without replaying page.__wgNetworkHistory (Node-side, survives
41
+ // navigation) back in every step, the "network tab" silently reset to empty on any step that
42
+ // navigated, instead of staying persistent like a real Network tab.
43
+ await restoreNetworkHistory(page);
44
+ // Explicit toggle too, not just the flag write above - covers the case where the panel already
45
+ // existed (no restore ran this step) and this step's `networkTabVisible` differs from before.
46
+ if (networkTabVisible !== undefined) {
47
+ await page.evaluate(setNetworkTabVisible, networkTabVisible).catch(() => {});
48
+ }
19
49
  // Runner-only chrome (step panel, zoom/typing/device chips) - separate key, no collision.
20
50
  await page.evaluate(([css, key]) => __wgCss(css, key), [RUNNER_EXTRA_CSS, "wg-runner-css"]).catch(() => {});
21
51
  await page.addStyleTag({ content: HOST_CSS }).catch(() => {});
@@ -36,6 +66,13 @@ export async function installOverlay(page, title, ui) {
36
66
  await page.evaluate(installPanelChrome, args).catch(() => {});
37
67
  await page.evaluate(installTodos, args).catch(() => {});
38
68
  await page.evaluate(installDevice, args).catch(() => {});
69
+ if (caption !== undefined) {
70
+ if (caption === "") {
71
+ await page.evaluate(hideCaption).catch(() => {});
72
+ } else {
73
+ await page.evaluate(showCaption, caption).catch(() => {});
74
+ }
75
+ }
39
76
  // Navigations wipe #wg-device-shell - rebuild when video stage + device are live.
40
77
  // If we already shuttered to desktop-flat, re-apply FLAT (never re-add bezel).
41
78
  if (