waygraph 0.12.10 → 0.12.11

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.
package/README.md CHANGED
@@ -215,11 +215,13 @@ overridable, not one giant Block with no per-step confirmation. `composedBlock.w
215
215
  `modStepVerify` patch one step from outside, addressed the same three ways
216
216
  `withBlockVerify`/`modBlockVerify` already are - a `composeBlock` result is a plain Block,
217
217
  so it drops straight into `defineFlow([start, ..., composed, ..., end])` like any other.
218
- `fastForwardComposeBlock(name, steps)` is the same shape marked for **demo pacing**: one
219
- opaque step (no per-inner gate) unless `waygraph demo --ff-expand`. Saucedemo
220
- `checkoutFlow` uses `ff-owner-auth` for the login prefix; `loginFlow` stays expanded for
221
- Sign In narration. Traverse (later) reuses FF as a seed prefix - see
222
- `docs/proposals/traverse-ffcompose-rfc.md`.
218
+ `fastForwardComposeBlock(name, steps)` is the same shape marked for **wall-clock
219
+ fast-forward**: one opaque demo step that **blitzes** (no per-inner gate, no smooth
220
+ cursor theater, Playwright slowMo off for that flow unless `WAYGRAPH_SLOWMO` is set)
221
+ unless `waygraph demo --ff-expand`. Put **several** FF units in one Flow when you need
222
+ to race past auth, then a heavy dashboard settle, then watch the interesting middle.
223
+ Saucedemo `checkoutFlow` uses `ff-owner-auth` for the login prefix; `loginFlow` stays
224
+ expanded for Sign In narration. See `docs/proposals/traverse-ffcompose-rfc.md`.
223
225
  `spawnTab(entry, page, mem)` drives a genuinely separate second tab through its own
224
226
  Block/Flow, in the same browser context an existing `page` already belongs to - the
225
227
  pattern `observe()` could already reach for (it's the only phase allowed to touch
package/dist/cli.js CHANGED
@@ -1745,10 +1745,10 @@ function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBefore
1745
1745
  // seconds. When slowMo is already doing the pacing, add none of our own;
1746
1746
  // only fall back to a small typing delay when slowMo is off entirely.
1747
1747
  //
1748
- // pacing.skipTheater (WAYGRAPH_FAST_BLOCKS only): near-zero cursor / pop /
1749
- // typing - blow past this block. --fast sets pacing.gatesFast instead
1750
- // and must NOT land here, or demo looks like plain waygraph run.
1751
- // stubBeforeRef.current = resolved stubBefore slots for the active block.
1748
+ // pacing.skipTheater (WAYGRAPH_FAST_BLOCKS **or** FFCompose): near-zero
1749
+ // cursor / pop / typing - blitz this step. --fast alone sets gatesFast only
1750
+ // (shorter Next/autoplay gates) and must NOT skip theater, or the whole demo
1751
+ // looks like plain waygraph run.
1752
1752
  const skipTheater = () => !!pacing.skipTheater;
1753
1753
  const typeDelay = () => (skipTheater() ? 0 : slowMo ? 0 : 30);
1754
1754
  // Click is a single action, not per-character, so it doesn't compound
@@ -1757,7 +1757,8 @@ function instrumentInteractionHighlighting(page, mem, slowMo, pacing, stubBefore
1757
1757
  // rather than stacking a full 1.2s on top of that.
1758
1758
  const clickPrePop = () => (skipTheater() ? 0 : slowMo ? 300 : 700);
1759
1759
  const clickPostPop = () => (skipTheater() ? 0 : slowMo ? 200 : 500);
1760
- const cursorMs = (full) => (skipTheater() ? Math.min(120, full) : full);
1760
+ // FF / FAST_BLOCKS: no cursor travel animation (0). Plain theater keeps full.
1761
+ const cursorMs = (full) => (skipTheater() ? 0 : full);
1761
1762
  // Locator.fill()/click() only ever see a raw call, no context of where
1762
1763
  // the value came from. Patching mem.get() to remember the most recently
1763
1764
  // read key's name (Blocks read-then-immediately-fill, e.g. const { email
@@ -1984,14 +1985,15 @@ async function resetPageState(context, page, baseURL) {
1984
1985
  async function runStepMode(engine, start, end, context, page, mem, resolved, slowMo, title, fastBlockNames, clearSession, baseURL) {
1985
1986
  // A shared, mutable pacing knob the interaction patches read live (per
1986
1987
  // call, not once at setup) - flipped per-block below so one block (e.g.
1987
- // WAYGRAPH_FAST_BLOCKS=login) can run through with none of the overlay's
1988
- // own added dwell while the rest of the chain keeps the full theatrical
1989
- // pace. Playwright's own slowMo is process-wide and untouched by this -
1990
- // only OUR added pauses (ring pop, cursor travel, typing delay) shrink
1991
- // when skipTheater is on.
1988
+ // WAYGRAPH_FAST_BLOCKS=login or an FFCompose unit) can run through with
1989
+ // none of the overlay's own added dwell while the rest of the chain keeps
1990
+ // the full theatrical pace.
1992
1991
  // --fast / WAYGRAPH_DEMO_FAST: shorter auto-next / Next gates ONLY -
1993
1992
  // keeps smooth cursor travel (not akin to waygraph run).
1994
- // WAYGRAPH_FAST_BLOCKS: named blocks still skip theater (old blow-past).
1993
+ // FFCompose + WAYGRAPH_FAST_BLOCKS: skipTheater (blitz overlay delays).
1994
+ // When the flow has any opaque FF unit and WAYGRAPH_SLOWMO is unset,
1995
+ // launch slowMo is 0 so Playwright itself does not re-tax every click
1996
+ // inside the FF (that was the "30s login / cursor gone but still slow" bug).
1995
1997
  const demoFast = process.env.WAYGRAPH_DEMO_FAST === "1";
1996
1998
  const stepperMode = process.env.WAYGRAPH_STEPPER === "full" ? "full" : "carousel";
1997
1999
  const pacing = { gatesFast: demoFast, skipTheater: false };
@@ -2081,8 +2083,11 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2081
2083
  // gates too, not just skip its interaction dwell - otherwise autoplay
2082
2084
  // still stalls the full autoplayMs admiring a step that intentionally
2083
2085
  // ran too fast to watch.
2084
- const ms =
2085
- pacing.gatesFast || pacing.skipTheater ? Math.min(400, autoplayMs) : autoplayMs;
2086
+ const ms = pacing.skipTheater
2087
+ ? Math.min(80, autoplayMs)
2088
+ : pacing.gatesFast
2089
+ ? Math.min(400, autoplayMs)
2090
+ : autoplayMs;
2086
2091
  let elapsed = 0;
2087
2092
  for (;;) {
2088
2093
  // Re-read the checkbox EVERY loop tick, not once up front - a human
@@ -2166,9 +2171,10 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2166
2171
  await resetPageState(context, page, baseURL);
2167
2172
  }
2168
2173
  // gatesFast: --fast (whole run) or FFCompose opaque steps (one short gate).
2169
- // skipTheater: only WAYGRAPH_FAST_BLOCKS - never --fast, never FF by default.
2174
+ // skipTheater: WAYGRAPH_FAST_BLOCKS **or** FFCompose — wall-clock blitz
2175
+ // (overlay delays). --fast alone never sets skipTheater.
2170
2176
  pacing.gatesFast = demoFast || !!r.block.fastForward;
2171
- pacing.skipTheater = fastBlockNames.has(r.block.name);
2177
+ pacing.skipTheater = fastBlockNames.has(r.block.name) || !!r.block.fastForward;
2172
2178
  const fixtures = r.highlightFixtures;
2173
2179
  stubBeforeRef.current = resolveHighlightSlots(r.block, "stubBefore", { fixtures });
2174
2180
  const isNavBlock = r.block.__waygraphKind === "nav";
@@ -2638,13 +2644,20 @@ async function main() {
2638
2644
  // nobody has to watch a live window for it to be right).
2639
2645
  const headed =
2640
2646
  process.env.WAYGRAPH_HEADED === "0" ? false : process.env.WAYGRAPH_HEADED === "1" || step;
2641
- // Step mode defaults to a visible pace (each fill/click actually shows on
2642
- // screen instead of snapping in) unless the human overrides it - an
2643
- // explicit WAYGRAPH_SLOWMO=0 still means "off".
2647
+ // Step mode defaults to a visible Playwright pace (slowMo 350) UNLESS the
2648
+ // flow has an opaque fastForwardComposeBlock — then default slowMo 0 so FF
2649
+ // auth/seed actually blitzes (<10s target) instead of only hiding the cursor
2650
+ // while every click still pays 350ms. Non-FF steps keep overlay theater
2651
+ // (cursor/pop) for watchability. Explicit WAYGRAPH_SLOWMO always wins.
2652
+ const hasOpaqueFf = resolved.some(
2653
+ (r) => r && r.block && r.block.fastForward === true,
2654
+ );
2644
2655
  const slowMo = process.env.WAYGRAPH_SLOWMO !== undefined
2645
2656
  ? Number(process.env.WAYGRAPH_SLOWMO)
2646
2657
  : step
2647
- ? 350
2658
+ ? hasOpaqueFf
2659
+ ? 0
2660
+ : 350
2648
2661
  : undefined;
2649
2662
  const baseURL = process.env.WAYGRAPH_BASE_URL;
2650
2663
  const title = process.env.WAYGRAPH_TITLE;
@@ -2652,8 +2665,8 @@ async function main() {
2652
2665
  // should blow past the overlay's own added dwell (ring pop, cursor
2653
2666
  // travel, typing delay, and that block's own gates) - "I want the login
2654
2667
  // block to be faster than the rest of the demo," Dan's own phrase.
2655
- // Playwright's real slowMo is untouched; this only trims what waygraph
2656
- // itself adds on top of it. Distinct from --fast (gates only).
2668
+ // FFCompose blocks get the same skipTheater automatically (no need to
2669
+ // list them here). Distinct from --fast (gates only).
2657
2670
  const fastBlockNames = new Set(
2658
2671
  (process.env.WAYGRAPH_FAST_BLOCKS || "")
2659
2672
  .split(",")
package/dist/engine.d.ts CHANGED
@@ -351,10 +351,13 @@ export declare function composeBlock<In extends Checkpoint<string>, B extends Ch
351
351
  export declare function composeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, D extends Checkpoint<string>, E extends Checkpoint<string>, F extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, D>, Block<D, E>, Block<E, F>, Block<F, Out>]): ComposedBlock<In, Out>;
352
352
  /**
353
353
  * Same shape as {@link composeBlock}, marked {@link FastForwardComposedBlock.fastForward}
354
- * so demo/run/traverse treat it as **one opaque step** (no per-inner gate/ring)
355
- * unless `--ff-expand` / `WAYGRAPH_FF_EXPAND=1`. Inner acts still run for real;
354
+ * so demo/run/traverse treat it as **one opaque step** that **blitzes wall-clock**
355
+ * (skip overlay theater + no Playwright slowMo on that step's acts) unless
356
+ * `--ff-expand` / `WAYGRAPH_FF_EXPAND=1`. Inner acts still run for real;
356
357
  * failures are prefixed `ff-name > …` so the locus names both the FF unit and
357
- * the inner step. Prefer this for boring prefixes (auth, seed) on demo Flows.
358
+ * the inner step. Prefer this for boring or heavy-check prefixes (auth, seed,
359
+ * dashboard settle) — you may put **several** FF units in one Flow with normal
360
+ * Blocks between them.
358
361
  * @example fastForwardComposeBlock("ff-owner-auth", [NavLoginBlock, SubmitLoginForFlow])
359
362
  */
360
363
  export interface FastForwardComposedBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> extends ComposedBlock<In, Out> {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.12.10",
3
+ "version": "0.12.11",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",