waygraph 0.15.53 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (556) hide show
  1. package/README.md +8 -3
  2. package/bin/waygraph +2 -2
  3. package/dist/analysis/check.d.ts +38 -0
  4. package/dist/analysis/check.js +87 -0
  5. package/dist/analysis/coverage-gap.d.ts +1 -1
  6. package/dist/analysis/coverage-gap.js +14 -37
  7. package/dist/analysis/flow-source.d.ts +9 -0
  8. package/dist/analysis/flow-source.js +25 -0
  9. package/dist/analysis/graph.d.ts +13 -14
  10. package/dist/analysis/graph.js +48 -371
  11. package/dist/analysis/map-check.js +4 -39
  12. package/dist/analysis/practices-check.d.ts +1 -1
  13. package/dist/analysis/practices-check.js +24 -45
  14. package/dist/cli/args.d.ts +23 -0
  15. package/dist/cli/args.js +20 -0
  16. package/dist/{cli.d.ts → cli/cli.d.ts} +0 -1
  17. package/dist/{cli.js → cli/cli.js} +10 -9
  18. package/dist/{commands → cli/commands}/agent-dive-scaffold.js +35 -64
  19. package/dist/cli/commands/agent-dive.js +42 -0
  20. package/dist/{commands → cli/commands}/check.d.ts +0 -1
  21. package/dist/cli/commands/check.js +104 -0
  22. package/dist/cli/commands/codemod-checkpoints.d.ts +18 -0
  23. package/dist/cli/commands/codemod-checkpoints.js +186 -0
  24. package/dist/cli/commands/codemod-flows.d.ts +18 -0
  25. package/dist/cli/commands/codemod-flows.js +284 -0
  26. package/dist/cli/commands/codemod-stubs.d.ts +10 -0
  27. package/dist/cli/commands/codemod-stubs.js +187 -0
  28. package/dist/{commands → cli/commands}/extensions.js +5 -4
  29. package/dist/{commands → cli/commands}/init.js +1 -2
  30. package/dist/{commands → cli/commands}/list.js +9 -7
  31. package/dist/cli/commands/manifest.d.ts +2 -0
  32. package/dist/cli/commands/manifest.js +20 -0
  33. package/dist/cli/commands/map.js +57 -0
  34. package/dist/{commands → cli/commands}/run.d.ts +0 -1
  35. package/dist/cli/commands/run.js +64 -0
  36. package/dist/{commands → cli/commands}/session.js +61 -88
  37. package/dist/{commands → cli/commands}/test.js +11 -14
  38. package/dist/cli/commands/traverse.js +105 -0
  39. package/dist/{commands → cli/commands}/try.js +29 -25
  40. package/dist/{commands → cli/commands}/upgrade.js +40 -4
  41. package/dist/cli/flags.d.ts +193 -16
  42. package/dist/cli/flags.js +179 -234
  43. package/dist/cli/run-chain.d.ts +1 -0
  44. package/dist/cli/run-chain.js +42 -7
  45. package/dist/cli/usage.d.ts +1 -1
  46. package/dist/cli/usage.js +21 -53
  47. package/dist/cli/util.d.ts +2 -2
  48. package/dist/cli/util.js +2 -3
  49. package/dist/{highlights → demo/narration}/css.d.ts +1 -1
  50. package/dist/{highlights → demo/narration}/css.js +2 -3
  51. package/dist/{highlights → demo/narration}/demo-pace.d.ts +7 -11
  52. package/dist/{highlights → demo/narration}/demo-pace.js +9 -11
  53. package/dist/{highlights → demo/narration}/device.d.ts +4 -2
  54. package/dist/{highlights → demo/narration}/device.js +3 -1
  55. package/dist/demo/narration/merge.d.ts +8 -0
  56. package/dist/demo/narration/merge.js +71 -0
  57. package/dist/{highlights/run-phase.d.ts → demo/narration/narration.d.ts} +10 -14
  58. package/dist/{highlights/run-phase.js → demo/narration/narration.js} +25 -94
  59. package/dist/{highlights → demo/narration}/shorthand.d.ts +1 -1
  60. package/dist/demo/narration/stub-ctx.d.ts +8 -0
  61. package/dist/demo/narration/stub-ctx.js +164 -0
  62. package/dist/{highlights → demo/narration}/style.d.ts +1 -7
  63. package/dist/{highlights → demo/narration}/style.js +1 -41
  64. package/dist/{highlights → demo/narration}/todo-dock.d.ts +3 -3
  65. package/dist/{highlights → demo/narration}/todo-dock.js +13 -30
  66. package/dist/demo/overlay/auto-chrome.d.ts +7 -0
  67. package/dist/demo/overlay/auto-chrome.js +97 -0
  68. package/dist/{session/overlay-beacon.d.ts → demo/overlay/beacon.d.ts} +7 -0
  69. package/dist/{session/overlay-beacon.js → demo/overlay/beacon.js} +5 -0
  70. package/dist/demo/overlay/cursor.d.ts +12 -0
  71. package/dist/demo/overlay/cursor.js +142 -0
  72. package/dist/demo/overlay/device-stage.d.ts +13 -0
  73. package/dist/demo/overlay/device-stage.js +396 -0
  74. package/dist/demo/overlay/inpage/banner.d.ts +1 -0
  75. package/dist/demo/overlay/inpage/banner.js +160 -0
  76. package/dist/demo/overlay/inpage/caption.d.ts +2 -0
  77. package/dist/demo/overlay/inpage/caption.js +24 -0
  78. package/dist/demo/overlay/inpage/core.d.ts +1 -0
  79. package/dist/demo/overlay/inpage/core.js +345 -0
  80. package/dist/demo/overlay/inpage/device-chip.d.ts +1 -0
  81. package/dist/demo/overlay/inpage/device-chip.js +191 -0
  82. package/dist/demo/overlay/inpage/network.d.ts +9 -0
  83. package/dist/demo/overlay/inpage/network.js +200 -0
  84. package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -0
  85. package/dist/demo/overlay/inpage/panel-chrome.js +203 -0
  86. package/dist/demo/overlay/inpage/stamp.d.ts +1 -0
  87. package/dist/demo/overlay/inpage/stamp.js +46 -0
  88. package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -0
  89. package/dist/demo/overlay/inpage/swipe-zoom.js +220 -0
  90. package/dist/demo/overlay/inpage/todos.d.ts +1 -0
  91. package/dist/demo/overlay/inpage/todos.js +294 -0
  92. package/dist/demo/overlay/locator-theater.d.ts +25 -0
  93. package/dist/demo/overlay/locator-theater.js +76 -0
  94. package/dist/demo/overlay/network-capture.d.ts +22 -0
  95. package/dist/demo/overlay/network-capture.js +127 -0
  96. package/dist/demo/overlay/overlay-css.d.ts +3 -0
  97. package/dist/demo/overlay/overlay-css.js +369 -0
  98. package/dist/demo/overlay/overlay-stage.d.ts +23 -0
  99. package/dist/demo/overlay/overlay-stage.js +106 -0
  100. package/dist/demo/overlay/overlay.d.ts +10 -0
  101. package/dist/demo/overlay/overlay.js +89 -0
  102. package/dist/{pilot-overlay/overlay-fixtures.d.ts → demo/overlay/phase-fixtures.d.ts} +2 -2
  103. package/dist/{pilot-overlay/overlay-fixtures.js → demo/overlay/phase-fixtures.js} +2 -2
  104. package/dist/{pilot-overlay/action-ring.js → demo/overlay/pilot/actions.js} +2 -1
  105. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.d.ts +6 -5
  106. package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.js +19 -18
  107. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.d.ts +2 -2
  108. package/dist/{pilot-overlay → demo/overlay/pilot}/shell.js +13 -22
  109. package/dist/demo/overlay/reattach.d.ts +7 -0
  110. package/dist/demo/overlay/reattach.js +23 -0
  111. package/dist/demo/overlay/rings.d.ts +33 -0
  112. package/dist/demo/overlay/rings.js +448 -0
  113. package/dist/{ui → demo/overlay/ui}/components/ring.js +2 -2
  114. package/dist/{ui → demo/overlay/ui}/overlay.css +4 -4
  115. package/dist/{ui → demo/overlay/ui}/shadow.d.ts +1 -1
  116. package/dist/{ui → demo/overlay/ui}/shadow.js +39 -2
  117. package/dist/demo/stepper/after.d.ts +3 -0
  118. package/dist/demo/stepper/after.js +113 -0
  119. package/dist/demo/stepper/banner-log.d.ts +37 -0
  120. package/dist/demo/stepper/banner-log.js +63 -0
  121. package/dist/demo/stepper/before.d.ts +4 -0
  122. package/dist/demo/stepper/before.js +110 -0
  123. package/dist/demo/stepper/demo-log.d.ts +31 -0
  124. package/dist/demo/stepper/demo-log.js +309 -0
  125. package/dist/demo/stepper/gate.d.ts +11 -0
  126. package/dist/demo/stepper/gate.js +78 -0
  127. package/dist/demo/stepper/interaction-patch.d.ts +3 -0
  128. package/dist/demo/stepper/interaction-patch.js +323 -0
  129. package/dist/demo/stepper/pacing.d.ts +21 -0
  130. package/dist/demo/stepper/pacing.js +23 -0
  131. package/dist/demo/stepper/slides.d.ts +11 -0
  132. package/dist/demo/stepper/slides.js +233 -0
  133. package/dist/demo/stepper/step-panels.d.ts +21 -0
  134. package/dist/demo/stepper/step-panels.js +589 -0
  135. package/dist/demo/stepper/stepper.d.ts +24 -0
  136. package/dist/demo/stepper/stepper.js +122 -0
  137. package/dist/demo/stepper/teardown.d.ts +48 -0
  138. package/dist/demo/stepper/teardown.js +179 -0
  139. package/dist/demo/stepper/todo-advance.d.ts +14 -0
  140. package/dist/demo/stepper/todo-advance.js +110 -0
  141. package/dist/demo/stepper/view.d.ts +68 -0
  142. package/dist/demo/stepper/view.js +31 -0
  143. package/dist/demo/types.d.ts +17 -0
  144. package/dist/demo/verbose-log.js +15 -0
  145. package/dist/{types.d.ts → engine/block/block.d.ts} +106 -91
  146. package/dist/{core → engine/block}/block.js +10 -53
  147. package/dist/{core → engine/block}/compose.d.ts +10 -7
  148. package/dist/{core → engine/block}/compose.js +1 -1
  149. package/dist/{core/blocks → engine/block/kinds}/api.d.ts +17 -12
  150. package/dist/{core/blocks → engine/block/kinds}/api.js +26 -18
  151. package/dist/{core/blocks → engine/block/kinds}/effect.d.ts +13 -18
  152. package/dist/engine/block/kinds/effect.js +17 -0
  153. package/dist/{core/blocks → engine/block/kinds}/method.d.ts +19 -29
  154. package/dist/{core/blocks → engine/block/kinds}/method.js +7 -21
  155. package/dist/{core/blocks → engine/block/kinds}/nav.d.ts +22 -31
  156. package/dist/{core/blocks → engine/block/kinds}/nav.js +6 -12
  157. package/dist/{core/blocks → engine/block/kinds}/page.d.ts +15 -20
  158. package/dist/{core/blocks → engine/block/kinds}/page.js +5 -7
  159. package/dist/engine/checkpoint/checkpoint.d.ts +22 -0
  160. package/dist/engine/checkpoint/checkpoint.js +8 -0
  161. package/dist/engine/checkpoint/route.d.ts +28 -0
  162. package/dist/engine/checkpoint/route.js +28 -0
  163. package/dist/{core → engine}/config.d.ts +7 -2
  164. package/dist/engine/config.js +6 -0
  165. package/dist/engine/engine.d.ts +45 -0
  166. package/dist/{core → engine}/engine.js +6 -10
  167. package/dist/engine/env.d.ts +59 -0
  168. package/dist/engine/env.js +83 -0
  169. package/dist/{errors.d.ts → engine/errors.d.ts} +23 -22
  170. package/dist/{errors.js → engine/errors.js} +22 -22
  171. package/dist/{core → engine/flow}/branch-regression.d.ts +8 -7
  172. package/dist/{core → engine/flow}/branch-regression.js +4 -3
  173. package/dist/engine/flow/flow.d.ts +162 -0
  174. package/dist/engine/flow/flow.js +244 -0
  175. package/dist/{core → engine/flow}/map-builder.d.ts +42 -40
  176. package/dist/{core → engine/flow}/map-builder.js +46 -48
  177. package/dist/{core → engine}/locate.d.ts +1 -1
  178. package/dist/{core → engine}/locate.js +1 -2
  179. package/dist/{mem-stub.d.ts → engine/mem/mem-stub.d.ts} +9 -8
  180. package/dist/{mem-stub.js → engine/mem/mem-stub.js} +2 -2
  181. package/dist/{mem-page.d.ts → engine/mem/mem.d.ts} +1 -1
  182. package/dist/{mem-page.js → engine/mem/mem.js} +2 -1
  183. package/dist/engine/page-gone.d.ts +5 -0
  184. package/dist/engine/page-gone.js +20 -0
  185. package/dist/engine/run/connect.d.ts +28 -0
  186. package/dist/{types.js → engine/run/connect.js} +11 -10
  187. package/dist/engine/run/events.d.ts +67 -0
  188. package/dist/engine/run/events.js +90 -0
  189. package/dist/engine/run/hooks.d.ts +16 -0
  190. package/dist/engine/run/hooks.js +8 -0
  191. package/dist/engine/run/launch.d.ts +13 -0
  192. package/dist/engine/run/launch.js +27 -0
  193. package/dist/{core/run-graph.d.ts → engine/run/run.d.ts} +9 -11
  194. package/dist/{core/run-graph.js → engine/run/run.js} +22 -11
  195. package/dist/engine/stub/pace.d.ts +12 -0
  196. package/dist/engine/stub/pace.js +2 -0
  197. package/dist/engine/stub/ring.d.ts +130 -0
  198. package/dist/engine/stub/ring.js +41 -0
  199. package/dist/engine/stub/stub.d.ts +268 -0
  200. package/dist/engine/stub/stub.js +1 -0
  201. package/dist/engine/stub/todos.d.ts +104 -0
  202. package/dist/engine/stub/todos.js +2 -0
  203. package/dist/engine/stub/viewport.d.ts +26 -0
  204. package/dist/engine/stub/viewport.js +2 -0
  205. package/dist/{trait.d.ts → engine/trait/trait.d.ts} +1 -1
  206. package/dist/index.d.ts +84 -36
  207. package/dist/index.js +44 -19
  208. package/dist/{session/auto-explore-run.d.ts → live/auto/auto.d.ts} +10 -16
  209. package/dist/{session/auto-explore-run.js → live/auto/auto.js} +164 -248
  210. package/dist/{session/auto-explore.d.ts → live/auto/explore.d.ts} +4 -14
  211. package/dist/{session/auto-explore.js → live/auto/explore.js} +21 -127
  212. package/dist/{auto-session/session.d.ts → live/auto-session/auto-session.d.ts} +1 -1
  213. package/dist/{auto-session/session.js → live/auto-session/auto-session.js} +27 -24
  214. package/dist/{auto-session → live/auto-session}/helpers.d.ts +16 -5
  215. package/dist/{auto-session → live/auto-session}/helpers.js +1 -1
  216. package/dist/{session/auto-session-ipc.d.ts → live/auto-session/ipc.d.ts} +7 -5
  217. package/dist/{session/auto-session-ipc.js → live/auto-session/ipc.js} +31 -16
  218. package/dist/{session/browser.d.ts → live/auto-session/start.d.ts} +1 -2
  219. package/dist/{session/browser.js → live/auto-session/start.js} +2 -3
  220. package/dist/{pilot-overlay → live/pilot}/panel.d.ts +1 -1
  221. package/dist/{pilot-overlay → live/pilot}/panel.js +23 -31
  222. package/dist/{session → live/pilot}/pilot.d.ts +4 -3
  223. package/dist/{session → live/pilot}/pilot.js +4 -4
  224. package/dist/{traverse → live/traverse}/coverage.d.ts +4 -0
  225. package/dist/{traverse → live/traverse}/coverage.js +3 -0
  226. package/dist/{traverse → live/traverse}/lease.d.ts +1 -0
  227. package/dist/{traverse → live/traverse}/lease.js +1 -0
  228. package/dist/{traverse/run.d.ts → live/traverse/traverse.d.ts} +4 -1
  229. package/dist/{traverse/run.js → live/traverse/traverse.js} +26 -43
  230. package/dist/manifest/manifest.d.ts +52 -0
  231. package/dist/manifest/manifest.js +93 -0
  232. package/dist/manifest/map-imports.d.ts +7 -0
  233. package/dist/manifest/map-imports.js +22 -0
  234. package/dist/manifest/maps.d.ts +33 -0
  235. package/dist/manifest/maps.js +62 -0
  236. package/dist/manifest/pack.d.ts +21 -0
  237. package/dist/manifest/pack.js +109 -0
  238. package/dist/manifest/project.d.ts +60 -0
  239. package/dist/manifest/project.js +101 -0
  240. package/dist/{session/block-inject.js → manifest/roots.js} +1 -18
  241. package/dist/manifest/scan.d.ts +19 -0
  242. package/dist/manifest/scan.js +57 -0
  243. package/dist/{blocks-select.d.ts → manifest/select.d.ts} +3 -0
  244. package/dist/{blocks-select.js → manifest/select.js} +2 -0
  245. package/dist/manifest/source.d.ts +23 -0
  246. package/dist/manifest/source.js +86 -0
  247. package/dist/runner/mode.d.ts +71 -0
  248. package/dist/runner/mode.js +1 -0
  249. package/dist/runner/modes/branches.d.ts +5 -0
  250. package/dist/runner/modes/branches.js +37 -0
  251. package/dist/runner/modes/demo.d.ts +3 -0
  252. package/dist/runner/modes/demo.js +13 -0
  253. package/dist/runner/modes/report.d.ts +2 -0
  254. package/dist/runner/modes/report.js +54 -0
  255. package/dist/runner/modes/run.d.ts +2 -0
  256. package/dist/runner/modes/run.js +3 -0
  257. package/dist/runner/options.d.ts +31 -0
  258. package/dist/runner/options.js +42 -0
  259. package/dist/runner/plan/find.d.ts +18 -0
  260. package/dist/runner/plan/find.js +65 -0
  261. package/dist/runner/plan/plan.d.ts +11 -0
  262. package/dist/runner/plan/plan.js +97 -0
  263. package/dist/runner/plan/seed-mem.d.ts +12 -0
  264. package/dist/runner/plan/seed-mem.js +98 -0
  265. package/dist/runner/plan/spec.d.ts +5 -0
  266. package/dist/runner/plan/spec.js +17 -0
  267. package/dist/runner/play-steps.d.ts +2 -0
  268. package/dist/runner/play-steps.js +59 -0
  269. package/dist/runner/runner.d.ts +4 -0
  270. package/dist/runner/runner.js +64 -0
  271. package/dist/runner/session.d.ts +9 -0
  272. package/dist/runner/session.js +87 -0
  273. package/dist/{browser.js → runtime/browser.js} +4 -2
  274. package/dist/{env-file.js → runtime/env-file.js} +7 -12
  275. package/dist/{extensions.d.ts → runtime/extensions.d.ts} +2 -5
  276. package/dist/{extensions.js → runtime/extensions.js} +3 -1
  277. package/dist/runtime/full-launch.d.ts +1 -0
  278. package/dist/runtime/full-launch.js +34 -0
  279. package/dist/runtime/global-flag.d.ts +5 -0
  280. package/dist/runtime/global-flag.js +18 -0
  281. package/dist/{playwright-config.d.ts → runtime/playwright-config.d.ts} +1 -1
  282. package/dist/{playwright.config.js → runtime/playwright.config.js} +3 -2
  283. package/dist/runtime/run-log.d.ts +2 -0
  284. package/dist/runtime/run-log.js +17 -0
  285. package/dist/{video-dir.js → runtime/video-dir.js} +3 -2
  286. package/dist/{config.d.ts → runtime/waygraph-config.d.ts} +8 -9
  287. package/dist/{config.js → runtime/waygraph-config.js} +21 -51
  288. package/dist/{webserver.js → runtime/webserver.js} +5 -30
  289. package/examples/routed-demo/config/waygraph.config.ts +20 -0
  290. package/examples/routed-demo/package.json +1 -4
  291. package/examples/routed-demo/scripts/fixture-server.mjs +1 -1
  292. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +2 -4
  293. package/examples/routed-demo/src/flows/routed-demo.flow.ts +2 -3
  294. package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +5 -4
  295. package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +3 -3
  296. package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +3 -3
  297. package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +3 -3
  298. package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +3 -3
  299. package/examples/routed-demo/src/states/routed-demo.states.ts +5 -3
  300. package/examples/routed-demo/tests/routed-demo.spec.ts +4 -4
  301. package/examples/routed-demo/tsconfig.json +1 -1
  302. package/examples/saucedemo/README.md +11 -12
  303. package/examples/saucedemo/config/waygraph.config.ts +17 -0
  304. package/examples/saucedemo/docs/CONVENTION.md +5 -7
  305. package/examples/saucedemo/docs/HELPERS.md +12 -12
  306. package/examples/saucedemo/package-lock.json +10 -3
  307. package/examples/saucedemo/package.json +12 -29
  308. package/examples/saucedemo/src/blocks/SITE-MAP.md +0 -1
  309. package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +1 -5
  310. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -52
  311. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  312. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  313. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  314. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  315. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  316. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +21 -27
  317. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -9
  318. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  319. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +10 -76
  320. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  321. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  322. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  323. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  324. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  325. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  326. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -29
  327. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -48
  328. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -77
  329. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  330. package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  331. package/examples/saucedemo/src/flows/api-demo.flow.ts +26 -18
  332. package/examples/saucedemo/src/flows/cart-bulk.flow.ts +19 -14
  333. package/examples/saucedemo/src/flows/cart-continue.flow.ts +10 -8
  334. package/examples/saucedemo/src/flows/cart-mem.flow.ts +7 -7
  335. package/examples/saucedemo/src/flows/catalog-logout.flow.ts +13 -8
  336. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +26 -48
  337. package/examples/saucedemo/src/flows/checkout.flow.ts +70 -86
  338. package/examples/saucedemo/src/flows/device-showcase.flow.ts +24 -25
  339. package/examples/saucedemo/src/flows/login.flow.ts +11 -18
  340. package/examples/saucedemo/src/flows/mem-stub-demo.flow.ts +9 -20
  341. package/examples/saucedemo/src/flows/shop.flow.ts +15 -20
  342. package/examples/saucedemo/src/flows/smoke.flow.ts +12 -27
  343. package/examples/saucedemo/src/flows/stub-on-error.flow.ts +24 -43
  344. package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +26 -34
  345. package/examples/saucedemo/src/states/checkout.mem-stubs.ts +11 -0
  346. package/examples/saucedemo/src/states/checkout.states.ts +21 -11
  347. package/examples/saucedemo/src/stubs/device-showcase.ts +191 -0
  348. package/examples/saucedemo/src/stubs/login.ts +37 -0
  349. package/examples/saucedemo/tests/auto-graph.spec.ts +4 -12
  350. package/examples/saucedemo/tests/chain-flow-episodes.spec.ts +7 -9
  351. package/examples/saucedemo/tests/submit-login-branch.spec.ts +18 -5
  352. package/package.json +12 -7
  353. package/templates/agents/waygraph-planner.agent.md +2 -2
  354. package/templates/quickstart/README.md +4 -7
  355. package/templates/quickstart/config/waygraph.config.ts +17 -0
  356. package/templates/quickstart/docs/CONVENTION.md +5 -6
  357. package/templates/quickstart/docs/HELPERS.md +11 -9
  358. package/templates/quickstart/package.json +14 -17
  359. package/templates/quickstart/src/blocks/SITE-MAP.md +13 -3
  360. package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +1 -5
  361. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -52
  362. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
  363. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
  364. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
  365. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
  366. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
  367. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +21 -27
  368. package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -9
  369. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
  370. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +10 -76
  371. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
  372. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
  373. package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  374. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
  375. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
  376. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
  377. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -29
  378. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -48
  379. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -77
  380. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
  381. package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
  382. package/templates/quickstart/src/flows/api-demo.flow.ts +45 -0
  383. package/templates/quickstart/src/flows/cart-bulk.flow.ts +19 -14
  384. package/templates/quickstart/src/flows/cart-continue.flow.ts +10 -8
  385. package/templates/quickstart/src/flows/cart-mem.flow.ts +7 -7
  386. package/templates/quickstart/src/flows/catalog-logout.flow.ts +13 -8
  387. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +26 -48
  388. package/templates/quickstart/src/flows/checkout.flow.ts +70 -63
  389. package/templates/quickstart/src/flows/device-showcase.flow.ts +24 -25
  390. package/templates/quickstart/src/flows/login.flow.ts +11 -18
  391. package/templates/quickstart/src/flows/mem-stub-demo.flow.ts +12 -0
  392. package/templates/quickstart/src/flows/shop.flow.ts +15 -20
  393. package/templates/quickstart/src/flows/smoke.flow.ts +12 -27
  394. package/templates/quickstart/src/flows/stub-on-error.flow.ts +31 -0
  395. package/templates/quickstart/src/flows/viewer-blocked.flow.ts +26 -34
  396. package/templates/quickstart/src/states/checkout.mem-stubs.ts +11 -0
  397. package/templates/quickstart/src/states/checkout.states.ts +21 -11
  398. package/templates/quickstart/src/stubs/device-showcase.ts +191 -0
  399. package/templates/quickstart/src/stubs/login.ts +37 -0
  400. package/templates/quickstart/tests/chain-flow.spec.ts +7 -10
  401. package/templates/scaffold/README.md +2 -1
  402. package/templates/scaffold/STRUCTURE.md +5 -4
  403. package/templates/scaffold/config/waygraph.config.ts +1 -0
  404. package/templates/scaffold/gitignore +1 -0
  405. package/templates/scaffold/src/flows/README.md +2 -2
  406. package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +3 -3
  407. package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +3 -3
  408. package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -4
  409. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +3 -3
  410. package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +3 -3
  411. package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +5 -4
  412. package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -4
  413. package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -3
  414. package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +3 -3
  415. package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +4 -4
  416. package/templates/scaffold/src/map/(external)/hoppscotch/_keys.ts +21 -0
  417. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +4 -4
  418. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +4 -4
  419. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +4 -4
  420. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +5 -4
  421. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +6 -5
  422. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +6 -5
  423. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +5 -4
  424. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +6 -5
  425. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +6 -5
  426. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +6 -5
  427. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +6 -5
  428. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +6 -5
  429. package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +6 -5
  430. package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +3 -3
  431. package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +3 -3
  432. package/templates/scaffold/src/map/(external)/hoppscotch/_states.ts +6 -0
  433. package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +3 -3
  434. package/templates/scaffold/src/map/(external)/mailpit/_keys.ts +13 -0
  435. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +4 -4
  436. package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +4 -4
  437. package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +6 -5
  438. package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +6 -5
  439. package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +3 -3
  440. package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +3 -3
  441. package/templates/scaffold/src/map/(external)/mailpit/_states.ts +9 -0
  442. package/templates/scaffold/src/map/README.md +7 -0
  443. package/templates/scaffold/src/states/README.md +4 -1
  444. package/templates/scaffold/src/states/demo.mem-keys.ts +1 -29
  445. package/templates/scaffold/src/states/demo.states.ts +14 -20
  446. package/templates/scaffold/tests/hoppscotch.spec.ts +1 -11
  447. package/templates/scaffold/tests/mail-verify.spec.ts +2 -2
  448. package/templates/skills/waygraph-blind-pilot.skill.md +2 -6
  449. package/templates/skills/waygraph-convention.skill.md +23 -14
  450. package/templates/skills/waygraph-pilot.skill.md +7 -4
  451. package/dist/auto-session/verbose-log.js +0 -16
  452. package/dist/auto-session.d.ts +0 -2
  453. package/dist/auto-session.js +0 -3
  454. package/dist/cli/discover.d.ts +0 -40
  455. package/dist/cli/discover.js +0 -148
  456. package/dist/commands/agent-dive.js +0 -52
  457. package/dist/commands/check.js +0 -192
  458. package/dist/commands/map.js +0 -29
  459. package/dist/commands/run.js +0 -104
  460. package/dist/commands/traverse.js +0 -177
  461. package/dist/core/block.d.ts +0 -109
  462. package/dist/core/blocks/effect.js +0 -23
  463. package/dist/core/config.js +0 -17
  464. package/dist/core/engine.d.ts +0 -198
  465. package/dist/core/flow.d.ts +0 -293
  466. package/dist/core/flow.js +0 -432
  467. package/dist/core.d.ts +0 -14
  468. package/dist/core.js +0 -15
  469. package/dist/highlights/merge.d.ts +0 -8
  470. package/dist/highlights/merge.js +0 -173
  471. package/dist/highlights/stub-ctx.d.ts +0 -10
  472. package/dist/highlights/stub-ctx.js +0 -331
  473. package/dist/highlights/types.d.ts +0 -607
  474. package/dist/highlights.d.ts +0 -9
  475. package/dist/highlights.js +0 -10
  476. package/dist/pilot-overlay.d.ts +0 -5
  477. package/dist/pilot-overlay.js +0 -6
  478. package/dist/runner/banner-log.js +0 -63
  479. package/dist/runner/chain-run.js +0 -102
  480. package/dist/runner/cursor.js +0 -140
  481. package/dist/runner/demo-log.js +0 -316
  482. package/dist/runner/device-stage.d.ts +0 -9
  483. package/dist/runner/device-stage.js +0 -420
  484. package/dist/runner/discovery.js +0 -105
  485. package/dist/runner/index.js +0 -2
  486. package/dist/runner/inpage/banner.d.ts +0 -21
  487. package/dist/runner/inpage/banner.js +0 -156
  488. package/dist/runner/inpage/caption.d.ts +0 -3
  489. package/dist/runner/inpage/caption.js +0 -23
  490. package/dist/runner/inpage/core.d.ts +0 -4
  491. package/dist/runner/inpage/core.js +0 -316
  492. package/dist/runner/inpage/device.d.ts +0 -3
  493. package/dist/runner/inpage/device.js +0 -211
  494. package/dist/runner/inpage/network.d.ts +0 -15
  495. package/dist/runner/inpage/network.js +0 -217
  496. package/dist/runner/inpage/panel-chrome.js +0 -192
  497. package/dist/runner/inpage/stamp.js +0 -46
  498. package/dist/runner/inpage/swipe-zoom.js +0 -220
  499. package/dist/runner/inpage/todos.js +0 -337
  500. package/dist/runner/interaction-patch.js +0 -384
  501. package/dist/runner/main.js +0 -469
  502. package/dist/runner/network-capture.d.ts +0 -9
  503. package/dist/runner/network-capture.js +0 -126
  504. package/dist/runner/overlay-css.d.ts +0 -3
  505. package/dist/runner/overlay-css.js +0 -377
  506. package/dist/runner/overlay-install.js +0 -90
  507. package/dist/runner/overlay-stage.js +0 -110
  508. package/dist/runner/rings.js +0 -514
  509. package/dist/runner/seed-mem.js +0 -110
  510. package/dist/runner/slides.js +0 -278
  511. package/dist/runner/step-mode.js +0 -703
  512. package/dist/runner/step-panels.js +0 -729
  513. package/dist/runner/teardown.js +0 -202
  514. package/dist/runner/todo-dock.js +0 -142
  515. package/dist/session/step-overlay.d.ts +0 -37
  516. package/dist/session/step-overlay.js +0 -244
  517. package/examples/routed-demo/playwright.config.ts +0 -21
  518. package/examples/saucedemo/playwright.config.ts +0 -19
  519. package/examples/saucedemo/scripts/drive-auto-cli.mjs +0 -93
  520. package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +0 -126
  521. package/examples/saucedemo/scripts/prove-auto-graph.mjs +0 -92
  522. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +0 -63
  523. package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  524. package/templates/quickstart/playwright.config.ts +0 -14
  525. package/templates/quickstart/scripts/drive-auto-cli.mjs +0 -93
  526. package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
  527. /package/dist/{commands → cli/commands}/agent-dive-scaffold.d.ts +0 -0
  528. /package/dist/{commands → cli/commands}/agent-dive.d.ts +0 -0
  529. /package/dist/{commands → cli/commands}/extensions.d.ts +0 -0
  530. /package/dist/{commands → cli/commands}/init.d.ts +0 -0
  531. /package/dist/{commands → cli/commands}/list.d.ts +0 -0
  532. /package/dist/{commands → cli/commands}/map.d.ts +0 -0
  533. /package/dist/{commands → cli/commands}/session.d.ts +0 -0
  534. /package/dist/{commands → cli/commands}/test.d.ts +0 -0
  535. /package/dist/{commands → cli/commands}/traverse.d.ts +0 -0
  536. /package/dist/{commands → cli/commands}/try.d.ts +0 -0
  537. /package/dist/{commands → cli/commands}/upgrade.d.ts +0 -0
  538. /package/dist/{highlights → demo/narration}/shorthand.js +0 -0
  539. /package/dist/{pilot-overlay/action-ring.d.ts → demo/overlay/pilot/actions.d.ts} +0 -0
  540. /package/dist/{ui → demo/overlay/ui}/components/ring.d.ts +0 -0
  541. /package/dist/{ui → demo/overlay/ui}/stylesheet.d.ts +0 -0
  542. /package/dist/{ui → demo/overlay/ui}/stylesheet.js +0 -0
  543. /package/dist/{ui → demo/overlay/ui}/tokens.d.ts +0 -0
  544. /package/dist/{ui → demo/overlay/ui}/tokens.js +0 -0
  545. /package/dist/{highlights → demo}/types.js +0 -0
  546. /package/dist/{auto-session → demo}/verbose-log.d.ts +0 -0
  547. /package/dist/{selector.d.ts → engine/trait/selector.d.ts} +0 -0
  548. /package/dist/{selector.js → engine/trait/selector.js} +0 -0
  549. /package/dist/{trait.js → engine/trait/trait.js} +0 -0
  550. /package/dist/{session/block-inject.d.ts → manifest/roots.d.ts} +0 -0
  551. /package/dist/{browser.d.ts → runtime/browser.d.ts} +0 -0
  552. /package/dist/{env-file.d.ts → runtime/env-file.d.ts} +0 -0
  553. /package/dist/{playwright-config.js → runtime/playwright-config.js} +0 -0
  554. /package/dist/{playwright.config.d.ts → runtime/playwright.config.d.ts} +0 -0
  555. /package/dist/{video-dir.d.ts → runtime/video-dir.d.ts} +0 -0
  556. /package/dist/{webserver.d.ts → runtime/webserver.d.ts} +0 -0
@@ -0,0 +1,448 @@
1
+ import { ANSI, ansiPaint, demoFixture, demoHighlight, demoLog } from "../stepper/demo-log.js";
2
+ import { playSwipeTrail } from "./cursor.js";
3
+ import { advanceTodoDock, normalizeTodos } from "../narration/todo-dock.js";
4
+ import { formatHighlightCaption } from "../narration/style.js";
5
+ import { normalizeHighlightSize, normalizeHighlightTone, normalizeHighlightWeight } from "../../engine/stub/ring.js";
6
+ import { resolveFixtureDwellMs } from "../narration/demo-pace.js";
7
+ import { envNumber } from "../../engine/env.js";
8
+ import { ignorePageGone } from "../../engine/page-gone.js";
9
+ /**
10
+ * Scroll a locator into view for demo theater.
11
+ * Prefer CSS smooth scroll + scrollend wait. Do NOT call Playwright's
12
+ * scrollIntoViewIfNeeded first - that jumps instantly and makes the
13
+ * following smooth scroll a no-op (looks like a teleport), especially
14
+ * noticeable under --fast when dwell is shorter.
15
+ * Pass opts.instant=true only for skipTheater / blitz.
16
+ */
17
+ export async function ensureLocatorInView(locator, opts) {
18
+ const instant = !!(opts && opts.instant);
19
+ if (instant) {
20
+ await locator.scrollIntoViewIfNeeded().catch(ignorePageGone);
21
+ return;
22
+ }
23
+ // Touch mode: if the target is off-screen, show a swipe trail in the
24
+ // finger direction that would scroll it into view (not device morph).
25
+ const scrollPlan = await locator
26
+ .evaluate((el) => {
27
+ if (!el || typeof el.getBoundingClientRect !== "function")
28
+ return null;
29
+ const touch = window.__wgDeviceTouch === true ||
30
+ document.documentElement.dataset.wgTouch === "1" ||
31
+ window.__wgDevicePreset === "mobile" ||
32
+ window.__wgDevicePreset === "tablet";
33
+ if (!touch)
34
+ return null;
35
+ const r = el.getBoundingClientRect();
36
+ const vw = window.innerWidth || 390;
37
+ const vh = window.innerHeight || 844;
38
+ const margin = 48;
39
+ const below = r.top > vh - margin;
40
+ const above = r.bottom < margin;
41
+ const right = r.left > vw - margin;
42
+ const left = r.right < margin;
43
+ if (!below && !above && !left && !right)
44
+ return null;
45
+ // Finger direction to reveal the target (swipe up => content moves up).
46
+ let dir = "up";
47
+ if (below)
48
+ dir = "up";
49
+ else if (above)
50
+ dir = "down";
51
+ else if (right)
52
+ dir = "left";
53
+ else if (left)
54
+ dir = "right";
55
+ return { dir, hint: "scroll" };
56
+ })
57
+ .catch(() => null);
58
+ if (scrollPlan && scrollPlan.dir) {
59
+ demoLog(" swipe trail dir=" + scrollPlan.dir + " hint=scroll");
60
+ await playSwipeTrail(locator.page(), {
61
+ dir: scrollPlan.dir,
62
+ label: "swipe \u00b7 scroll",
63
+ hint: "scroll",
64
+ ms: envNumber("WAYGRAPH_SWIPE_MS") ?? 650,
65
+ });
66
+ }
67
+ await locator
68
+ .evaluate(async (el) => {
69
+ if (!el || typeof el.scrollIntoView !== "function")
70
+ return;
71
+ const waitScroll = (node, ms) => new Promise((resolve) => {
72
+ let done = false;
73
+ const finish = () => {
74
+ if (done)
75
+ return;
76
+ done = true;
77
+ try {
78
+ node.removeEventListener("scrollend", finish);
79
+ }
80
+ catch {
81
+ /* ignore */
82
+ }
83
+ clearTimeout(t);
84
+ resolve();
85
+ };
86
+ const t = setTimeout(finish, ms);
87
+ try {
88
+ node.addEventListener("scrollend", finish, { once: true });
89
+ }
90
+ catch {
91
+ /* scrollend unsupported - timeout only */
92
+ }
93
+ });
94
+ try {
95
+ el.scrollIntoView({ block: "center", inline: "center", behavior: "smooth" });
96
+ }
97
+ catch {
98
+ try {
99
+ el.scrollIntoView({ block: "center", inline: "center" });
100
+ }
101
+ catch {
102
+ try {
103
+ el.scrollIntoView(true);
104
+ }
105
+ catch {
106
+ /* ignore */
107
+ }
108
+ }
109
+ }
110
+ await waitScroll(document.scrollingElement || document.documentElement, 650);
111
+ let p = el.parentElement;
112
+ while (p && p !== document.documentElement && p !== document.body) {
113
+ const st = getComputedStyle(p);
114
+ const ox = st.overflowX;
115
+ const oy = st.overflowY;
116
+ if (/(auto|scroll|overlay)/.test(ox) || /(auto|scroll|overlay)/.test(oy)) {
117
+ const er = el.getBoundingClientRect();
118
+ const pr = p.getBoundingClientRect();
119
+ if (er.left < pr.left || er.right > pr.right || er.top < pr.top || er.bottom > pr.bottom) {
120
+ const left = p.scrollLeft + (er.left + er.width / 2 - (pr.left + pr.width / 2));
121
+ const top = p.scrollTop + (er.top + er.height / 2 - (pr.top + pr.height / 2));
122
+ try {
123
+ p.scrollTo({ left, top, behavior: "smooth" });
124
+ }
125
+ catch {
126
+ p.scrollLeft = left;
127
+ p.scrollTop = top;
128
+ }
129
+ await waitScroll(p, 650);
130
+ }
131
+ }
132
+ p = p.parentElement;
133
+ }
134
+ })
135
+ .catch(ignorePageGone);
136
+ }
137
+ export async function ensureSelectorInView(page, selector, opts) {
138
+ await ensureLocatorInView(page.locator(selector).first(), opts);
139
+ }
140
+ export async function applyHighlightZoom(page, selector, zoom, zoomOut) {
141
+ const z = Number(zoom);
142
+ if (!Number.isFinite(z) || z <= 1.001) {
143
+ await page.evaluate(() => {
144
+ window.__wgZoomOutOnHide = true;
145
+ if (window.__wgClearZoom)
146
+ window.__wgClearZoom();
147
+ }).catch(ignorePageGone);
148
+ return;
149
+ }
150
+ demoFixture("zoom", "ctx/ring zoom(" + z + ") zoomOut=" + (zoomOut !== false), selector);
151
+ await page
152
+ .evaluate(({ sel, scale, zoomOut }) => {
153
+ // false = keep camera after ring hide (ctx.zoomOut(false) / ring.zoomOut).
154
+ window.__wgZoomOutOnHide = zoomOut !== false;
155
+ if (window.__wgApplyZoom)
156
+ window.__wgApplyZoom(sel, scale);
157
+ }, { sel: selector, scale: z, zoomOut: zoomOut !== false })
158
+ .catch(ignorePageGone);
159
+ }
160
+ export async function cycleHighlightRings(page, highlights, gatesFast, opts) {
161
+ const list = highlights || [];
162
+ // defaultHoldMs: when set (fail path), use instead of the default 900/200 so BUG
163
+ // rings stay visible ~2s before the error panel (PIA stubOnError RFC).
164
+ const defaultHoldMs = opts && opts.defaultHoldMs != null ? opts.defaultHoldMs : null;
165
+ const pace = opts && opts.pace !== undefined ? opts.pace : undefined;
166
+ let dock = opts && opts.todoDock;
167
+ const advanceTodos = !(opts && opts.advanceTodos === false);
168
+ // Push stubAfter/before dock before the first ring so Method after-panels
169
+ // show the updated checklist immediately (not only after the ring cycle).
170
+ if (dock) {
171
+ await page
172
+ .evaluate((d) => {
173
+ if (window.__wgSyncTodos)
174
+ window.__wgSyncTodos({ sync: "set", dock: d });
175
+ }, dock)
176
+ .catch(ignorePageGone);
177
+ }
178
+ else if (opts && opts.todoSync === "clear") {
179
+ await page
180
+ .evaluate(() => {
181
+ if (window.__wgSyncTodos)
182
+ window.__wgSyncTodos({ sync: "clear" });
183
+ })
184
+ .catch(ignorePageGone);
185
+ }
186
+ let lastRingEndedAt = null;
187
+ for (let i = 0; i < list.length; i++) {
188
+ const h = list[i];
189
+ const ringStarted = Date.now();
190
+ try {
191
+ await ensureSelectorInView(page, h.selector);
192
+ await applyHighlightZoom(page, h.selector, h.zoom, h.zoomOut);
193
+ // Prefer live in-page rect (honors device-shell scale) over Playwright's own boundingBox() -
194
+ // but resolve the element through Playwright's OWN locator (full selector engine: >>
195
+ // piercing, :has-text(), :visible, ...), not a raw DOM querySelector, which only understands
196
+ // real CSS and silently fails to match any Playwright-specific selector syntax.
197
+ // count() gate: a real, caught regression - Locator.evaluate() has no timeout option and
198
+ // auto-waits (Playwright's default ~30s) for a match to appear, unlike the instant
199
+ // document.querySelector it replaced. count() alone never waits, so this stays an immediate
200
+ // "does it exist right now" check - ensureSelectorInView above already gave the page a real
201
+ // moment to settle.
202
+ const hLoc = page.locator(h.selector).first();
203
+ const box = (await hLoc.count().catch(() => 0)) > 0
204
+ ? await hLoc
205
+ .evaluate((el) => {
206
+ const r = el.getBoundingClientRect();
207
+ return { x: r.x, y: r.y, width: r.width, height: r.height };
208
+ })
209
+ .catch(() => null)
210
+ : null;
211
+ if (box && box.width > 0 && box.height > 0) {
212
+ await showRing(page, box, h.label, h.tone || "planned", {
213
+ size: h.size,
214
+ weight: h.weight,
215
+ selector: h.selector,
216
+ focus: !!h.focus,
217
+ });
218
+ // focus is applied by FollowRing / showRing - no second apply needed
219
+ // Do NOT advanceTodoDock by ring index after stubAfter already set
220
+ // progress - that reset current back to 0 and the next block looked
221
+ // blank. Mid-act Method advance still uses syncTodoDockAdvance.
222
+ if (dock && advanceTodos) {
223
+ dock = advanceTodoDock(dock, i);
224
+ if (opts && opts.todoDockRef)
225
+ opts.todoDockRef.current = dock;
226
+ await page
227
+ .evaluate((d) => {
228
+ if (window.__wgSyncTodos)
229
+ window.__wgSyncTodos({ sync: "set", dock: d });
230
+ }, dock)
231
+ .catch(ignorePageGone);
232
+ }
233
+ else if (!dock && ((opts && opts.todos && opts.todos.length) || (h.todos && h.todos.length))) {
234
+ const rows = opts && opts.todos && opts.todos.length
235
+ ? opts.todos
236
+ : normalizeTodos(h.todos, h.todoIndex);
237
+ await page
238
+ .evaluate((todos) => {
239
+ if (window.__wgSyncTodos)
240
+ window.__wgSyncTodos({ sync: "set", list: todos });
241
+ }, rows)
242
+ .catch(ignorePageGone);
243
+ }
244
+ const authored = resolveFixtureDwellMs(h, { gatesFast, pace });
245
+ const defaultMs = i === list.length - 1 ? 200 : 900;
246
+ const holdMs = authored != null ? authored : defaultHoldMs != null ? defaultHoldMs : defaultMs;
247
+ const gap = lastRingEndedAt != null ? ringStarted - lastRingEndedAt : null;
248
+ const holdExtra = "hold=" +
249
+ holdMs +
250
+ "ms" +
251
+ (authored != null ? " authored" : " default") +
252
+ " box=" +
253
+ Math.round(box.x) +
254
+ "," +
255
+ Math.round(box.y) +
256
+ " " +
257
+ Math.round(box.width) +
258
+ "x" +
259
+ Math.round(box.height) +
260
+ (gap != null ? " gap=" + gap + "ms" : "");
261
+ demoHighlight(h, holdExtra);
262
+ demoLog(" highlight " +
263
+ (i + 1) +
264
+ "/" +
265
+ list.length +
266
+ (gap != null && gap < 120 ? ansiPaint(ANSI.yellow, " WARN gap<120ms") : "") +
267
+ (holdMs < 250 && list.length > 1 ? ansiPaint(ANSI.yellow, " WARN short hold") : ""));
268
+ await new Promise((res) => setTimeout(res, holdMs));
269
+ lastRingEndedAt = Date.now();
270
+ }
271
+ else {
272
+ demoHighlight(h, "SKIP no boundingBox");
273
+ }
274
+ }
275
+ catch (err) {
276
+ demoHighlight(h || { selector: h && h.selector, label: "(error)" }, "SKIP " + String(err instanceof Error ? err.message : err).slice(0, 80));
277
+ }
278
+ }
279
+ if (list.length > 0) {
280
+ const last = list[list.length - 1];
281
+ // Resolved through Playwright's own locator (>> piercing / :has-text() / :visible support),
282
+ // not handed to the page as a string for a raw DOM querySelector to fail silently on - see
283
+ // showRing's own comment (same fix, same reason) and __wgFollowRing's in core.js.
284
+ const handle = last.selector
285
+ ? await page.locator(last.selector).first().elementHandle({ timeout: 100 }).catch(() => null)
286
+ : null;
287
+ await page
288
+ .evaluate(({ h, el }) => {
289
+ if (el && window.__wgFollowRing) {
290
+ window.__wgFollowRing(el, h.label, h.tone || "planned", { size: h.size || "md", weight: h.weight || "normal" }, !!h.focus);
291
+ return;
292
+ }
293
+ if (!window.__wgPositionRing)
294
+ return;
295
+ if (!el) {
296
+ if (window.__wgHideRing)
297
+ window.__wgHideRing();
298
+ return;
299
+ }
300
+ const reposition = () => {
301
+ const box = el.getBoundingClientRect();
302
+ window.__wgPositionRing(box, h.label, h.tone || "planned", {
303
+ size: h.size || "md",
304
+ weight: h.weight || "normal",
305
+ });
306
+ if (h.focus && window.__wgApplyFocus) {
307
+ window.__wgApplyFocus({
308
+ x: box.x,
309
+ y: box.y,
310
+ width: box.width,
311
+ height: box.height,
312
+ });
313
+ }
314
+ };
315
+ reposition();
316
+ window.__wgRingTrack = reposition;
317
+ window.addEventListener("resize", reposition);
318
+ window.addEventListener("scroll", reposition, true);
319
+ }, { h: last, el: handle })
320
+ .catch(ignorePageGone);
321
+ }
322
+ else {
323
+ await hideRing(page);
324
+ }
325
+ }
326
+ export async function showRing(page, box, label, tone, style) {
327
+ const size = normalizeHighlightSize(style && style.size);
328
+ const weight = normalizeHighlightWeight(style && style.weight);
329
+ const selector = style && style.selector ? String(style.selector) : "";
330
+ const focus = !!(style && style.focus);
331
+ // Resolve through Playwright's own locator (full selector engine), not a selector string handed
332
+ // to the page for a raw DOM lookup - >> piercing / :has-text() / :visible are Playwright-only
333
+ // syntax, invisible to document.querySelector. The resolved element handle is passed straight
334
+ // into evaluate (Playwright unwraps it to the real DOM node inside the page), so __wgFollowRing's
335
+ // per-frame RAF loop tracks that exact element directly - no repeated selector re-resolution.
336
+ const handle = selector ? await page.locator(selector).first().elementHandle({ timeout: 100 }).catch(() => null) : null;
337
+ await page
338
+ .evaluate(({ box, label, tone, size, weight, el, focus }) => {
339
+ if (el && window.__wgFollowRing) {
340
+ window.__wgFollowRing(el, label, tone || "planned", { size, weight }, focus);
341
+ return;
342
+ }
343
+ if (window.__wgStopRingFollow)
344
+ window.__wgStopRingFollow();
345
+ if (window.__wgPositionRing) {
346
+ window.__wgPositionRing(box, label, tone || "planned", { size, weight });
347
+ }
348
+ if (focus && box && window.__wgApplyFocus)
349
+ window.__wgApplyFocus(box);
350
+ else if (!focus && window.__wgClearFocus)
351
+ window.__wgClearFocus();
352
+ }, { box, label, tone: tone || "planned", size, weight, el: handle, focus })
353
+ .catch(ignorePageGone);
354
+ }
355
+ /** Match a locator to a stubBefore slot by overlapping bounding boxes. */
356
+ async function matchStubForLocator(page, locator, stubs) {
357
+ if (!stubs || stubs.length === 0)
358
+ return null;
359
+ const box = await locator.boundingBox().catch(() => null);
360
+ if (!box)
361
+ return null;
362
+ for (const s of stubs) {
363
+ try {
364
+ const b = await page.locator(s.selector).first().boundingBox();
365
+ if (b &&
366
+ Math.abs(b.x - box.x) < 4 &&
367
+ Math.abs(b.y - box.y) < 4 &&
368
+ Math.abs(b.width - box.width) < 8) {
369
+ return s;
370
+ }
371
+ }
372
+ catch {
373
+ // A stub selector Playwright can't parse can't be this element either.
374
+ }
375
+ }
376
+ return null;
377
+ }
378
+ /** 0-based stub index for Method fill/click todo advance; -1 if none. */
379
+ export async function matchStubIndexForLocator(page, locator, stubs) {
380
+ if (!stubs || stubs.length === 0)
381
+ return -1;
382
+ const box = await locator.boundingBox().catch(() => null);
383
+ if (!box)
384
+ return -1;
385
+ for (let i = 0; i < stubs.length; i++) {
386
+ const s = stubs[i];
387
+ try {
388
+ const b = await page.locator(s.selector).first().boundingBox();
389
+ if (b &&
390
+ Math.abs(b.x - box.x) < 4 &&
391
+ Math.abs(b.y - box.y) < 4 &&
392
+ Math.abs(b.width - box.width) < 8) {
393
+ return i;
394
+ }
395
+ }
396
+ catch {
397
+ // A stub selector Playwright can't parse can't be this element either.
398
+ }
399
+ }
400
+ return -1;
401
+ }
402
+ export async function captionForLocator(page, locator, stubs, fallback) {
403
+ const matched = await matchStubForLocator(page, locator, stubs);
404
+ if (matched) {
405
+ return {
406
+ label: formatHighlightCaption(matched),
407
+ tone: normalizeHighlightTone(matched.tone),
408
+ size: normalizeHighlightSize(matched.size),
409
+ weight: normalizeHighlightWeight(matched.weight),
410
+ };
411
+ }
412
+ return { label: fallback, tone: "auto", size: "md", weight: "normal" };
413
+ }
414
+ export async function dwellMatchedStub(page, locator, stubs, pacing) {
415
+ const matched = await matchStubForLocator(page, locator, stubs);
416
+ if (!matched)
417
+ return;
418
+ const ms = resolveFixtureDwellMs(matched, {
419
+ gatesFast: !!(pacing && pacing.gatesFast),
420
+ pace: pacing && pacing.demoPace,
421
+ });
422
+ if (ms != null && ms > 0) {
423
+ await new Promise((res) => setTimeout(res, ms));
424
+ }
425
+ }
426
+ export async function hideRing(page) {
427
+ await page
428
+ .evaluate(() => {
429
+ if (window.__wgHideRing)
430
+ window.__wgHideRing();
431
+ })
432
+ .catch(ignorePageGone);
433
+ }
434
+ /**
435
+ * True if the engine's own narrate() (waygraph's public export, for a Block
436
+ * author explicitly captioning one action) JUST positioned the ring for
437
+ * THIS action, moments ago - the automatic per-fill/per-click narration
438
+ * below should not immediately overwrite an author's own explicit caption
439
+ * with its generic guess.
440
+ */
441
+ export async function wasJustNarrated(page) {
442
+ return page
443
+ .evaluate(() => {
444
+ const w = window;
445
+ return typeof w.__wgLastNarrate === "number" && Date.now() - w.__wgLastNarrate < 500;
446
+ })
447
+ .catch(() => false);
448
+ }
@@ -33,5 +33,5 @@ export function ringCss() {
33
33
  }
34
34
  // A former `pilotFxRingCss()` used to live here, generating a SECOND, byte-identical copy of
35
35
  // ringCss()'s own rules under `.wg-pilot-fx-ring`/`.wg-pilot-fx-label`. Pilot's fixture rings now
36
- // paint through the same shared primitive (`ui/css/ring.css`'s `.wg-ring-el`, `runner/inpage/core.js`'s
37
- // `__wgPaintRingAt`) as the demo/auto singleton ring - see src/ui/css/ring.css's own header.
36
+ // paint through the same shared primitive (`ui/css/ring.css`'s `.wg-ring-el`, `demo/overlay/inpage/core.ts`'s
37
+ // `__wgPaintRingAt`) as the demo/auto singleton ring - see src/demo/overlay/ui/css/ring.css's own header.
@@ -1,4 +1,4 @@
1
- /* Bundled at build time by scripts/copy-ui-css.mjs - do not hand-edit. Edit src/ui/css/*.css. */
1
+ /* Bundled at build time by scripts/copy-ui-css.mjs - do not hand-edit. Edit src/demo/overlay/ui/css/*.css. */
2
2
 
3
3
  :host{--layer-1:1;--layer-2:2;--layer-3:3;--layer-4:4;--layer-5:5;--layer-important:2147483647}
4
4
 
@@ -54,7 +54,7 @@
54
54
  * ONE ring implementation, shared by every surface (demo/auto's singleton #wg-ring, and Pilot's
55
55
  * multiple simultaneous fixture rings) - `.wg-ring-el`/`.wg-ring-el-label` is the real class every
56
56
  * ring element carries; `#wg-ring`/`#wg-ring-label` and Pilot's per-instance ids are just how each
57
- * surface finds/targets ITS OWN ring(s) in JS (runner/inpage/core.js's __wgEnsureRingEl/
57
+ * surface finds/targets ITS OWN ring(s) in JS (demo/overlay/inpage/core.ts's __wgEnsureRingEl/
58
58
  * __wgPaintRingAt). Before this file existed as one, the demo/auto ring and Pilot's fixture ring
59
59
  * were two byte-identical copies of the same tone/size/weight rules - a real, provable case of the
60
60
  * "why do we have two of everything" complaint that's easy to lose track of once it's spread across
@@ -132,7 +132,7 @@
132
132
 
133
133
  /* Top title banner (#wg-banner). Sits BELOW the ring/label/dock layers (--wg-z-banner) - a title
134
134
  * card must never shadow a highlight; see tokens.css. Moves out of the way of a ring it overlaps
135
- * (data-collision, driven from inpage/banner.js's __wgBannerAvoidRing) unless authored off. */
135
+ * (data-collision, driven from inpage/banner.ts's __wgBannerAvoidRing) unless authored off. */
136
136
  #wg-banner {
137
137
  position: fixed; z-index: var(--wg-z-banner); top: 14px; left: 14px;
138
138
  background: var(--wg-surface); color: #fff; border-radius: var(--wg-radius-lg); padding: 10px 16px;
@@ -154,7 +154,7 @@
154
154
 
155
155
  /*
156
156
  * Floating fixture todo dock for Pilot (#wg-pilot-fx-todos). The demo runner's OWN `.wg-todo-dock` /
157
- * `#wg-todo-dock` (src/runner/overlay-css.js) is a separate, richer implementation - fold/tucked/
157
+ * `#wg-todo-dock` (demo/overlay/overlay-css.ts) is a separate, richer implementation - fold/tucked/
158
158
  * slide-position transitions this file does not replicate - and deliberately NOT redefined here:
159
159
  * two rule sets for the same selector, injected in different orders, is exactly the "sometimes it
160
160
  * doesn't line up" bug class this split guards against. Only #wg-pilot-fx-todos, a genuine
@@ -10,7 +10,7 @@
10
10
  import type { Page } from "@playwright/test";
11
11
  /**
12
12
  * `overlaySheet` is the ONE real-CSS bundle (`ui/stylesheet.ts` -> `dist/ui/overlay.css`, built on
13
- * Open Props - see `src/ui/css/README.md`) every surface shares; passed in from Node since in-page
13
+ * Open Props - see `src/demo/overlay/ui/css/README.md`) every surface shares; passed in from Node since in-page
14
14
  * code can't read a file. Installed once per shadow root, before anything else runs.
15
15
  */
16
16
  export declare function installShadowRoot(overlaySheet?: string): void;
@@ -1,7 +1,8 @@
1
1
  import { getOverlaySheet } from "./stylesheet.js";
2
+ import { ignorePageGone } from "../../../engine/page-gone.js";
2
3
  /**
3
4
  * `overlaySheet` is the ONE real-CSS bundle (`ui/stylesheet.ts` -> `dist/ui/overlay.css`, built on
4
- * Open Props - see `src/ui/css/README.md`) every surface shares; passed in from Node since in-page
5
+ * Open Props - see `src/demo/overlay/ui/css/README.md`) every surface shares; passed in from Node since in-page
5
6
  * code can't read a file. Installed once per shadow root, before anything else runs.
6
7
  */
7
8
  export function installShadowRoot(overlaySheet) {
@@ -37,10 +38,46 @@ export function installShadowRoot(overlaySheet) {
37
38
  if (style.textContent !== css)
38
39
  style.textContent = css;
39
40
  };
41
+ const toNodes = (children, out = []) => {
42
+ for (const c of children) {
43
+ if (c == null || c === false)
44
+ continue;
45
+ if (Array.isArray(c))
46
+ toNodes(c, out);
47
+ else
48
+ out.push(c instanceof Node ? c : document.createTextNode(String(c)));
49
+ }
50
+ return out;
51
+ };
52
+ w.__wgEl = (tag, props, ...children) => {
53
+ const el = document.createElement(tag);
54
+ if (props?.id)
55
+ el.id = props.id;
56
+ if (props?.class)
57
+ el.className = props.class;
58
+ if (props?.style)
59
+ el.style.cssText = props.style;
60
+ if (props?.title)
61
+ el.title = props.title;
62
+ for (const [k, v] of Object.entries(props?.data ?? {}))
63
+ if (v != null)
64
+ el.dataset[k] = String(v);
65
+ for (const [k, v] of Object.entries(props?.attrs ?? {}))
66
+ if (v != null)
67
+ el.setAttribute(k, String(v));
68
+ el.append(...toNodes(children));
69
+ return el;
70
+ };
71
+ w.__wgSet = (el, ...children) => el.replaceChildren(...toNodes(children));
72
+ // Waygraph's own static icons (constants in this package, never page or author text), parsed as SVG.
73
+ w.__wgSvg = (markup) => {
74
+ const xml = markup.includes("xmlns=") ? markup : markup.replace("<svg", '<svg xmlns="http://www.w3.org/2000/svg"');
75
+ return document.importNode(new DOMParser().parseFromString(xml, "image/svg+xml").documentElement, true);
76
+ };
40
77
  if (overlaySheet)
41
78
  w.__wgCss(overlaySheet, "wg-overlay-css");
42
79
  }
43
80
  /** Idempotent; call before any overlay install on a page. Installs the shared stylesheet bundle. */
44
81
  export async function ensureShadowRoot(page) {
45
- await page.evaluate(installShadowRoot, getOverlaySheet()).catch(() => { });
82
+ await page.evaluate(installShadowRoot, getOverlaySheet()).catch(ignorePageGone);
46
83
  }
@@ -0,0 +1,3 @@
1
+ import type { Checkpoint } from "../../engine/checkpoint/checkpoint.js";
2
+ import type { StepperContext, StepView } from "./view.js";
3
+ export declare function showAfter(ctx: StepperContext, view: StepView, result: Checkpoint<string>): Promise<void>;
@@ -0,0 +1,113 @@
1
+ import { hasAuthoredStubAfter, resolveSlides, runStubPhase } from "../narration/narration.js";
2
+ import { applyHighlightStyleDefaults, formatHighlightCaption } from "../narration/style.js";
3
+ import { demoLog, logStubPhaseFixtures, logTodoDockFull, paceSpeakFields, summarizeDevice } from "./demo-log.js";
4
+ import { extractVerifyHighlights, renderAfterStep } from "./step-panels.js";
5
+ import { presentSlides } from "./slides.js";
6
+ import { logBannerDom, probeBanner } from "./banner-log.js";
7
+ import { logDocks } from "./before.js";
8
+ import { forceCollapsed } from "./view.js";
9
+ import { envFlag } from "../../engine/env.js";
10
+ const quiet = () => envFlag("WAYGRAPH_JSON");
11
+ export async function showAfter(ctx, view, result) {
12
+ const { stage, refs } = ctx;
13
+ await showSlides(ctx, view, result);
14
+ const after = hasAuthoredStubAfter(view.step.block, result) ? await narrateAfter(ctx, view, result) : undefined;
15
+ const applied = after ? await stage.applyPhase(after.phase) : { appliedTodo: { sync: "keep" }, appliedDevice: { sync: "keep" } };
16
+ await renderAfterStep(ctx.page, {
17
+ index: view.index,
18
+ total: ctx.steps.length,
19
+ blockName: view.step.block.name,
20
+ result,
21
+ resultTag: JSON.stringify(result),
22
+ highlights: after?.highlights ?? verifyRings(view, result),
23
+ gatesFast: ctx.pacing.gatesFast,
24
+ ...paceSpeakFields(ctx.pacing.demoPace, ctx.gate.autoplayMs),
25
+ isLast: view.index === ctx.steps.length - 1,
26
+ allNames: view.moduleNames,
27
+ allDescriptions: view.moduleDescriptions,
28
+ moduleIndex: view.moduleIndex,
29
+ allEpisodes: ctx.allEpisodes,
30
+ title: after?.phase.title && String(after.phase.title).trim() ? String(after.phase.title).trim() : view.overlayTitle,
31
+ bannerUi: stage.state.lastBannerUi,
32
+ // undefined leaves the caption and network tab as they are
33
+ caption: after?.phase.caption,
34
+ networkTabVisible: after?.phase.networkTabVisible,
35
+ fastForward: !!view.step.block.fastForward,
36
+ isApi: view.step.block.__waygraphKind === "api",
37
+ todoPos: after ? stage.state.lastTodoDock?.pos || after.phase.todoPos || view.overlayTodoPos : view.overlayTodoPos,
38
+ episodeNumber: view.step.episodeNumber,
39
+ episodeTitle: view.step.episodeTitle,
40
+ stepperMode: ctx.stepperMode,
41
+ todos: after ? stage.state.lastTodoDock?.groups[0]?.items || after.phase.todos || [] : [],
42
+ todoDock: stage.state.lastTodoDock,
43
+ todoSync: applied.appliedTodo.sync,
44
+ todoId: stage.state.lastTodoDock?.id,
45
+ todoDockRef: refs.todoDock,
46
+ forceCollapsed: forceCollapsed(),
47
+ });
48
+ const parallel = !!after?.phase.todoParallel;
49
+ await stage.syncAllTodoDocks({ parallel });
50
+ // The ring cycle or stubAfter may have advanced the dock; the next step starts from there.
51
+ if (refs.todoDock.current) {
52
+ stage.state.lastTodoDock = refs.todoDock.current;
53
+ stage.rememberTodoDock(refs.todoDock.current, "set", parallel);
54
+ }
55
+ if (!quiet()) {
56
+ demoLog(" after " + summarizeDevice(stage.state.lastDevice) + " deviceSync=" + applied.appliedDevice.sync);
57
+ logTodoDockFull(stage.state.lastTodoDock, " after");
58
+ demoLog(" after todoSync=" + applied.appliedTodo.sync);
59
+ await logDocks(ctx, "after ", !!stage.state.lastTodoDock, applied.appliedTodo.sync === "clear");
60
+ logBannerDom("after", await probeBanner(ctx.page));
61
+ }
62
+ await ctx.gate.wait();
63
+ }
64
+ async function showSlides(ctx, view, result) {
65
+ const slides = resolveSlides(view.step.block, { out: result }).map((s) => applyHighlightStyleDefaults(s, view.step.highlightStyle));
66
+ if (slides.length === 0)
67
+ return;
68
+ await presentSlides(ctx.page, slides, ctx.gate.wait, {
69
+ title: ctx.title,
70
+ blockName: view.step.block.name,
71
+ fast: ctx.pacing.gatesFast,
72
+ pace: ctx.pacing.demoPace,
73
+ episodeNumber: view.step.episodeNumber,
74
+ episodeTitle: view.step.episodeTitle,
75
+ autoplayMs: ctx.gate.autoplayMs,
76
+ });
77
+ }
78
+ /** Runs the Block's stubAfter; its rings carry the flow's highlight style and a caption. */
79
+ async function narrateAfter(ctx, view, result) {
80
+ const style = view.step.highlightStyle;
81
+ const phase = await runStubPhase(view.step.block, "stubAfter", { out: result, mem: ctx.mem });
82
+ if (phase.todoDockUi)
83
+ await ctx.stage.pushTodoDockUi(phase.todoDockUi);
84
+ logStubPhaseFixtures("after", {
85
+ ...phase,
86
+ highlights: (phase.highlights || []).map((h) => {
87
+ const styled = applyHighlightStyleDefaults(h, style);
88
+ return { ...styled, label: formatHighlightCaption(styled) };
89
+ }),
90
+ });
91
+ const highlights = phase.highlights.map((h) => {
92
+ const styled = applyHighlightStyleDefaults(h, style);
93
+ return {
94
+ selector: styled.selector,
95
+ label: formatHighlightCaption(styled),
96
+ duration: styled.duration,
97
+ fastMode: styled.fastMode,
98
+ tone: styled.tone,
99
+ size: styled.size,
100
+ weight: styled.weight,
101
+ zoom: styled.zoom,
102
+ zoomOut: styled.zoomOut,
103
+ focus: !!styled.focus,
104
+ color: styled.color,
105
+ detail: styled.detail,
106
+ };
107
+ });
108
+ return { phase, highlights };
109
+ }
110
+ /** No stubAfter: ring what the Block's verify checked. */
111
+ function verifyRings(view, result) {
112
+ return extractVerifyHighlights(view.step.block, result.__state).map((h) => applyHighlightStyleDefaults(h, view.step.highlightStyle));
113
+ }