waygraph 0.12.11 → 0.12.13

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
@@ -218,10 +218,15 @@ so it drops straight into `defineFlow([start, ..., composed, ..., end])` like an
218
218
  `fastForwardComposeBlock(name, steps)` is the same shape marked for **wall-clock
219
219
  fast-forward**: one opaque demo step that **blitzes** (no per-inner gate, no smooth
220
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`.
221
+ unless expanded. Put **several** FF units in one Flow when you need to race past auth,
222
+ then a heavy dashboard settle, then watch the interesting middle.
223
+
224
+ **Dispute / disable FF:** `waygraph demo --ff-disabled` (alias `--no-ff`) expands every
225
+ FFCompose into its inner Blocks so a broken login step is visible as its own panel row.
226
+ Former FF inners keep blitz pacing so wall-clock stays comparable to opaque FF (same
227
+ real acts). `--ff-expand` is the older expand-only flag (same flatten). Saucedemo
228
+ `checkoutFlow` uses `ff-owner-auth` for the login prefix; `loginFlow` stays expanded for
229
+ Sign In narration. See `docs/proposals/traverse-ffcompose-rfc.md`.
225
230
  `spawnTab(entry, page, mem)` drives a genuinely separate second tab through its own
226
231
  Block/Flow, in the same browser context an existing `page` already belongs to - the
227
232
  pattern `observe()` could already reach for (it's the only phase allowed to touch
@@ -251,6 +251,8 @@ export async function buildExploreMenu(page, graph, library, here) {
251
251
  if (!(await navRunnable(page, entry)))
252
252
  continue;
253
253
  if (here === null) {
254
+ // Bootstrap only: URL deep-links as "Start here". Click-nav needs a live
255
+ // control so it cannot seed an unknown page.
254
256
  if (!isUrlNav(entry))
255
257
  continue;
256
258
  push(navigate, edge);
@@ -258,6 +260,12 @@ export async function buildExploreMenu(page, graph, library, here) {
258
260
  }
259
261
  if (edge.to === here)
260
262
  continue;
263
+ // Known screen: do NOT dump every defineNavBlock({ url }) under Navigate.
264
+ // Graph still marks NavBlocks from:"*" for pathfinding/traverse; auto menu
265
+ // only offers click-nav whose control is visible on this page (navRunnable).
266
+ // Otherwise LoginForm lists every app route + mailpit as if legal moves.
267
+ if (isUrlNav(entry))
268
+ continue;
261
269
  if (isBackEdge(edge) && (edge.from === here || edge.from === "*")) {
262
270
  push(back, edge);
263
271
  }
package/dist/cli.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Primary verbs (less is more):
6
6
  * auto Explore picker; `.flow.ts` / `--blocks From To` = run that path
7
- * demo Watch (step overlay); `--blocks` `--data` `--auto-next` `--fast` `--full` `--ff-expand`
7
+ * demo Watch (step overlay); `--blocks` `--data` `--auto-next` `--fast` `--full` `--ff-expand` `--ff-disabled`
8
8
  * run Execute; `--blocks` `--data` `--non-headless` `--video`
9
9
  *
10
10
  * Also: list / nav / validate / check / graph / init / agent-dive / traverse / try
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Primary verbs (less is more):
6
6
  * auto Explore picker; `.flow.ts` / `--blocks From To` = run that path
7
- * demo Watch (step overlay); `--blocks` `--data` `--auto-next` `--fast` `--full` `--ff-expand`
7
+ * demo Watch (step overlay); `--blocks` `--data` `--auto-next` `--fast` `--full` `--ff-expand` `--ff-disabled`
8
8
  * run Execute; `--blocks` `--data` `--non-headless` `--video`
9
9
  *
10
10
  * Also: list / nav / validate / check / graph / init / agent-dive / traverse / try
@@ -2170,11 +2170,11 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
2170
2170
  if ((clearSession || r.resetSession) && i > 0) {
2171
2171
  await resetPageState(context, page, baseURL);
2172
2172
  }
2173
- // gatesFast: --fast (whole run) or FFCompose opaque steps (one short gate).
2174
- // skipTheater: WAYGRAPH_FAST_BLOCKS **or** FFCompose — wall-clock blitz
2175
- // (overlay delays). --fast alone never sets skipTheater.
2176
- pacing.gatesFast = demoFast || !!r.block.fastForward;
2177
- pacing.skipTheater = fastBlockNames.has(r.block.name) || !!r.block.fastForward;
2173
+ // gatesFast / skipTheater: opaque FF, former-FF inners (--ff-disabled/--ff-expand),
2174
+ // or WAYGRAPH_FAST_BLOCKS. --fast alone = shorter gates only (keeps theater).
2175
+ pacing.gatesFast = demoFast || !!r.block.fastForward || !!r.wasFastForward;
2176
+ pacing.skipTheater =
2177
+ fastBlockNames.has(r.block.name) || !!r.block.fastForward || !!r.wasFastForward;
2178
2178
  const fixtures = r.highlightFixtures;
2179
2179
  stubBeforeRef.current = resolveHighlightSlots(r.block, "stubBefore", { fixtures });
2180
2180
  const isNavBlock = r.block.__waygraphKind === "nav";
@@ -2484,7 +2484,9 @@ async function main() {
2484
2484
  // truly unexpected failure outside runJsonReportMode's own try/catch)
2485
2485
  // reaches stdout.
2486
2486
  const jsonReport = process.env.WAYGRAPH_JSON === "1";
2487
- const ffExpand = process.env.WAYGRAPH_FF_EXPAND === "1";
2487
+ const ffExpand =
2488
+ process.env.WAYGRAPH_FF_EXPAND === "1" || process.env.WAYGRAPH_FF_DISABLED === "1";
2489
+ const ffDisabled = process.env.WAYGRAPH_FF_DISABLED === "1";
2488
2490
  /** Expand or keep fastForwardComposeBlock units for demo/run step lists. */
2489
2491
  const flattenBlockInfos = (blockInfos) => {
2490
2492
  const out = [];
@@ -2497,6 +2499,10 @@ async function main() {
2497
2499
  block: step.block,
2498
2500
  ...(step.routes ? { routes: step.routes } : {}),
2499
2501
  ...(bi.resetSessionBefore ? { resetSessionBefore: true } : {}),
2502
+ // Dispute / --ff-disabled: keep blitz pacing on former FF inners so
2503
+ // wall-clock stays comparable to opaque FF (same real acts).
2504
+ wasFastForward: true,
2505
+ ffSource: b.name,
2500
2506
  });
2501
2507
  }
2502
2508
  } else {
@@ -2529,14 +2535,20 @@ async function main() {
2529
2535
  flow.expectedFailureReason && idx === blockInfos.length - 1
2530
2536
  ? flow.expectedFailureReason
2531
2537
  : undefined,
2538
+ ...(bi.wasFastForward ? { wasFastForward: true, ffSource: bi.ffSource } : {}),
2532
2539
  }));
2533
2540
  chainFlows = [flow];
2534
2541
  if (!jsonReport) {
2535
2542
  console.log(
2536
- "waygraph: running existing flow \\"" + bareRef + "\\" - " +
2543
+ 'waygraph: running existing flow "' + bareRef + '" - ' +
2537
2544
  resolved.map((r) => r.block.name).join(" -> ") + " (" + resolved.length + " block" +
2538
2545
  (resolved.length === 1 ? "" : "s") + ", no chain spec needed)",
2539
2546
  );
2547
+ if (ffDisabled) {
2548
+ console.error(
2549
+ "waygraph demo: --ff-disabled - FFCompose expanded to inners (dispute / step locus); blitz pacing kept on former FF steps",
2550
+ );
2551
+ }
2540
2552
  }
2541
2553
  }
2542
2554
  }
@@ -2623,6 +2635,7 @@ async function main() {
2623
2635
  expectedFailureReason:
2624
2636
  meta.expectedFailureReason && remainingInFlow === 1 ? meta.expectedFailureReason : undefined,
2625
2637
  seedMem: isFirstOfSegment ? meta.seedMem : undefined,
2638
+ ...(bi.wasFastForward ? { wasFastForward: true, ffSource: bi.ffSource } : {}),
2626
2639
  };
2627
2640
  remainingInFlow -= 1;
2628
2641
  isFirstOfSegment = false;
@@ -2644,21 +2657,27 @@ async function main() {
2644
2657
  // nobody has to watch a live window for it to be right).
2645
2658
  const headed =
2646
2659
  process.env.WAYGRAPH_HEADED === "0" ? false : process.env.WAYGRAPH_HEADED === "1" || step;
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,
2660
+ // Step mode: blitz Playwright slowMo when any opaque FF **or** former-FF
2661
+ // inners (--ff-disabled) are in the resolved list. Explicit WAYGRAPH_SLOWMO wins.
2662
+ const hasFfBlitz = resolved.some(
2663
+ (r) =>
2664
+ r &&
2665
+ ((r.block && r.block.fastForward === true) || r.wasFastForward === true),
2654
2666
  );
2655
2667
  const slowMo = process.env.WAYGRAPH_SLOWMO !== undefined
2656
2668
  ? Number(process.env.WAYGRAPH_SLOWMO)
2657
2669
  : step
2658
- ? hasOpaqueFf
2670
+ ? hasFfBlitz
2659
2671
  ? 0
2660
2672
  : 350
2661
2673
  : undefined;
2674
+ if (step && hasFfBlitz && process.env.WAYGRAPH_SLOWMO === undefined && !jsonReport) {
2675
+ console.error(
2676
+ ffDisabled
2677
+ ? "waygraph demo: --ff-disabled (expanded) → Playwright slowMo=0 on former FF steps (blitz; same acts as opaque FF)"
2678
+ : "waygraph demo: opaque FFCompose in flow → Playwright slowMo=0 (blitz); set WAYGRAPH_SLOWMO to override",
2679
+ );
2680
+ }
2662
2681
  const baseURL = process.env.WAYGRAPH_BASE_URL;
2663
2682
  const title = process.env.WAYGRAPH_TITLE;
2664
2683
  // Comma-separated Block names (their real .name, e.g. "login") that
@@ -3355,6 +3374,10 @@ function parseRunFlags(argv) {
3355
3374
  else if (a === "--ff-expand") {
3356
3375
  out.ffExpand = true;
3357
3376
  }
3377
+ else if (a === "--ff-disabled" || a === "--no-ff") {
3378
+ out.ffDisabled = true;
3379
+ out.ffExpand = true;
3380
+ }
3358
3381
  else if (a === "--non-headless") {
3359
3382
  out.nonHeadless = true;
3360
3383
  }
@@ -3516,6 +3539,10 @@ function applyRunFlags(flags, opts) {
3516
3539
  if (flags.ffExpand) {
3517
3540
  process.env.WAYGRAPH_FF_EXPAND = "1";
3518
3541
  }
3542
+ if (flags.ffDisabled) {
3543
+ process.env.WAYGRAPH_FF_DISABLED = "1";
3544
+ process.env.WAYGRAPH_FF_EXPAND = "1";
3545
+ }
3519
3546
  }
3520
3547
  /**
3521
3548
  * BASE_URL when neither --base-url nor WAYGRAPH_BASE_URL is set:
@@ -3674,6 +3701,7 @@ Primary (less is more):
3674
3701
  --fast Shorter auto-next / Next gates (keeps smooth cursor)
3675
3702
  --full Classic wrap-all block chips (default: carousel)
3676
3703
  --ff-expand Expand fastForwardComposeBlock inners as separate steps
3704
+ --ff-disabled Dispute: expand FF (alias --no-ff); blitz kept on those inners
3677
3705
  --auto-play-video Unattended + recorded: --auto-next + --video (+ step); headless by default
3678
3706
  --auto-play-video-head Same, but keep the browser visible (--non-headless)
3679
3707
  --video-viewport WxH Recording size (default demo: 1920x1080)
@@ -3684,6 +3712,7 @@ Primary (less is more):
3684
3712
  --video [dir] Record .webm
3685
3713
  --video-viewport WxH Recording size (default run: 1280x720)
3686
3714
  --ff-expand Same as demo (expand FFCompose inners)
3715
+ --ff-disabled Same as demo (dispute: expand FF)
3687
3716
 
3688
3717
  Also:
3689
3718
  waygraph list | nav | validate | check | graph | init <name>
@@ -4006,7 +4035,7 @@ Agents shipped: waygraph-planner, waygraph-author, waygraph-healer.
4006
4035
  console.error("waygraph demo: missing flow/spec — e.g.\n" +
4007
4036
  " waygraph demo src/flows/shop.flow.ts\n" +
4008
4037
  " waygraph demo --blocks shopFlow\n" +
4009
- " Flags: --blocks --data --auto-next --fast --full --ff-expand --auto-play-video --title --base-url --video");
4038
+ " Flags: --blocks --data --auto-next --fast --full --ff-expand --ff-disabled --auto-play-video --title --base-url --video");
4010
4039
  process.exit(1);
4011
4040
  }
4012
4041
  const proj = flags.blocks
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.12.11",
3
+ "version": "0.12.13",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",