waygraph 0.15.53 → 0.15.54

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 (108) hide show
  1. package/dist/analysis/graph.d.ts +3 -0
  2. package/dist/auto-session/helpers.d.ts +10 -0
  3. package/dist/blocks-select.d.ts +3 -0
  4. package/dist/blocks-select.js +2 -0
  5. package/dist/config.d.ts +2 -0
  6. package/dist/core/blocks/api.d.ts +1 -0
  7. package/dist/core/blocks/method.d.ts +2 -0
  8. package/dist/core/blocks/method.js +1 -0
  9. package/dist/core/blocks/nav.d.ts +1 -0
  10. package/dist/core/blocks/page.d.ts +1 -0
  11. package/dist/core/branch-regression.d.ts +1 -0
  12. package/dist/core/compose.d.ts +1 -0
  13. package/dist/core/flow.d.ts +1 -0
  14. package/dist/core/map-builder.d.ts +8 -1
  15. package/dist/core/map-builder.js +1 -1
  16. package/dist/core/run-graph.d.ts +2 -0
  17. package/dist/core/run-graph.js +1 -0
  18. package/dist/errors.d.ts +1 -0
  19. package/dist/extensions.d.ts +1 -0
  20. package/dist/extensions.js +1 -0
  21. package/dist/highlights/demo-pace.d.ts +4 -0
  22. package/dist/highlights/demo-pace.js +4 -0
  23. package/dist/highlights/device.d.ts +2 -0
  24. package/dist/highlights/device.js +2 -0
  25. package/dist/highlights/types.d.ts +6 -0
  26. package/dist/session/auto-explore-run.js +6 -0
  27. package/dist/session/overlay-beacon.d.ts +7 -0
  28. package/dist/session/overlay-beacon.js +5 -0
  29. package/dist/session/pilot.d.ts +1 -0
  30. package/dist/traverse/coverage.d.ts +4 -0
  31. package/dist/traverse/coverage.js +3 -0
  32. package/dist/traverse/lease.d.ts +1 -0
  33. package/dist/traverse/lease.js +1 -0
  34. package/dist/traverse/run.d.ts +3 -0
  35. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +1 -1
  36. package/examples/routed-demo/src/flows/routed-demo.flow.ts +2 -2
  37. package/examples/saucedemo/README.md +11 -12
  38. package/examples/saucedemo/config/waygraph.config.ts +17 -0
  39. package/examples/saucedemo/docs/CONVENTION.md +1 -2
  40. package/examples/saucedemo/docs/HELPERS.md +1 -1
  41. package/examples/saucedemo/package-lock.json +10 -3
  42. package/examples/saucedemo/package.json +12 -29
  43. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +0 -49
  44. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +22 -25
  45. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +0 -6
  46. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +38 -96
  47. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +1 -26
  48. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +1 -45
  49. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +14 -77
  50. package/examples/saucedemo/src/flows/api-demo.flow.ts +17 -11
  51. package/examples/saucedemo/src/flows/cart-bulk.flow.ts +19 -14
  52. package/examples/saucedemo/src/flows/cart-continue.flow.ts +10 -8
  53. package/examples/saucedemo/src/flows/cart-mem.flow.ts +7 -7
  54. package/examples/saucedemo/src/flows/catalog-logout.flow.ts +13 -8
  55. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +26 -48
  56. package/examples/saucedemo/src/flows/checkout.flow.ts +70 -86
  57. package/examples/saucedemo/src/flows/device-showcase.flow.ts +24 -25
  58. package/examples/saucedemo/src/flows/login.flow.ts +11 -18
  59. package/examples/saucedemo/src/flows/mem-stub-demo.flow.ts +9 -20
  60. package/examples/saucedemo/src/flows/shop.flow.ts +15 -20
  61. package/examples/saucedemo/src/flows/smoke.flow.ts +12 -27
  62. package/examples/saucedemo/src/flows/stub-on-error.flow.ts +24 -43
  63. package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +26 -34
  64. package/examples/saucedemo/src/states/checkout.mem-stubs.ts +11 -0
  65. package/examples/saucedemo/src/stubs/device-showcase.ts +193 -0
  66. package/examples/saucedemo/src/stubs/login.ts +37 -0
  67. package/examples/saucedemo/tests/chain-flow-episodes.spec.ts +7 -9
  68. package/examples/saucedemo/tests/submit-login-branch.spec.ts +18 -5
  69. package/package.json +3 -2
  70. package/templates/quickstart/README.md +4 -7
  71. package/templates/quickstart/config/waygraph.config.ts +17 -0
  72. package/templates/quickstart/docs/CONVENTION.md +1 -2
  73. package/templates/quickstart/docs/HELPERS.md +1 -1
  74. package/templates/quickstart/package.json +14 -14
  75. package/templates/quickstart/src/blocks/SITE-MAP.md +14 -3
  76. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +0 -49
  77. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +22 -25
  78. package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +0 -6
  79. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +38 -96
  80. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +1 -26
  81. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +1 -45
  82. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +14 -77
  83. package/templates/quickstart/src/flows/api-demo.flow.ts +43 -0
  84. package/templates/quickstart/src/flows/cart-bulk.flow.ts +19 -14
  85. package/templates/quickstart/src/flows/cart-continue.flow.ts +10 -8
  86. package/templates/quickstart/src/flows/cart-mem.flow.ts +7 -7
  87. package/templates/quickstart/src/flows/catalog-logout.flow.ts +13 -8
  88. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +26 -48
  89. package/templates/quickstart/src/flows/checkout.flow.ts +70 -63
  90. package/templates/quickstart/src/flows/device-showcase.flow.ts +24 -25
  91. package/templates/quickstart/src/flows/login.flow.ts +11 -18
  92. package/templates/quickstart/src/flows/mem-stub-demo.flow.ts +12 -0
  93. package/templates/quickstart/src/flows/shop.flow.ts +15 -20
  94. package/templates/quickstart/src/flows/smoke.flow.ts +12 -27
  95. package/templates/quickstart/src/flows/stub-on-error.flow.ts +31 -0
  96. package/templates/quickstart/src/flows/viewer-blocked.flow.ts +26 -34
  97. package/templates/quickstart/src/states/checkout.mem-stubs.ts +11 -0
  98. package/templates/quickstart/src/stubs/device-showcase.ts +193 -0
  99. package/templates/quickstart/src/stubs/login.ts +37 -0
  100. package/templates/quickstart/tests/chain-flow.spec.ts +7 -10
  101. package/templates/skills/waygraph-convention.skill.md +1 -1
  102. package/examples/saucedemo/playwright.config.ts +0 -19
  103. package/examples/saucedemo/scripts/drive-auto-cli.mjs +0 -93
  104. package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +0 -126
  105. package/examples/saucedemo/scripts/prove-auto-graph.mjs +0 -92
  106. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +0 -63
  107. package/templates/quickstart/playwright.config.ts +0 -14
  108. package/templates/quickstart/scripts/drive-auto-cli.mjs +0 -93
@@ -8,6 +8,7 @@ import { type BlocksSelect } from "../blocks-select.js";
8
8
  export interface WaygraphNode {
9
9
  checkpoint: string;
10
10
  }
11
+ /** A move in the graph: a Block from one Checkpoint tag to another. */
11
12
  export interface WaygraphEdge {
12
13
  /** The Block's own runtime `.name`. */
13
14
  block: string;
@@ -18,11 +19,13 @@ export interface WaygraphEdge {
18
19
  to: string;
19
20
  kind: "nav" | "action";
20
21
  }
22
+ /** A Block `waygraph graph` found but could not place in the graph, with the reason. */
21
23
  export interface SkippedBlock {
22
24
  block: string;
23
25
  file: string;
24
26
  reason: string;
25
27
  }
28
+ /** The static graph of a project: Checkpoint nodes, Block edges, skipped and orphan Blocks. */
26
29
  export interface WaygraphGraph {
27
30
  nodes: WaygraphNode[];
28
31
  edges: WaygraphEdge[];
@@ -3,6 +3,7 @@ import type { BlockEntry, ExploreMenu } from "../session/auto-explore.js";
3
3
  import type { PickResult } from "../session/auto-explore-run.js";
4
4
  /** True when a stub-phase result actually carries authored content worth keeping. */
5
5
  export declare function stubPhaseHasContent(r: StubPhaseResult): boolean;
6
+ /** One available move in a session snapshot: a Block and the Checkpoint it leads to. */
6
7
  export interface SessionSnapshotEdge {
7
8
  /** 1-based, matching the numbers a human/agent picks by (same as printCliMenu). */
8
9
  index: number;
@@ -12,10 +13,12 @@ export interface SessionSnapshotEdge {
12
13
  label?: string;
13
14
  description?: string;
14
15
  }
16
+ /** A group of moves in a session snapshot, by page. */
15
17
  export interface SessionSnapshotSection {
16
18
  title: string;
17
19
  edges: SessionSnapshotEdge[];
18
20
  }
21
+ /** The state of a live session: where it is, the moves available from there, and the trace so far. */
19
22
  export interface SessionSnapshot {
20
23
  here: string | null;
21
24
  sections: SessionSnapshotSection[];
@@ -82,6 +85,7 @@ export declare function walkFullDom(root: Element, caps: FullDomCaps): {
82
85
  tree: FullDomNode;
83
86
  truncated: boolean;
84
87
  };
88
+ /** What `AutoSession.start` needs: project, selection, headless mode and the session id. */
85
89
  export interface AutoSessionInit {
86
90
  projectDir: string;
87
91
  baseURL?: string;
@@ -102,6 +106,7 @@ export interface AutoSessionInit {
102
106
  */
103
107
  sessionId?: string;
104
108
  }
109
+ /** The result of running one menu pick in a live session. */
105
110
  export type ApplyPickResult = {
106
111
  ok: true;
107
112
  snapshot: SessionSnapshot;
@@ -110,6 +115,7 @@ export type ApplyPickResult = {
110
115
  ok: false;
111
116
  error: string;
112
117
  };
118
+ /** The result of running a multi-step route in a live session. */
113
119
  export type ApplyPathResult = {
114
120
  ok: true;
115
121
  path: string[];
@@ -141,6 +147,7 @@ export interface TraceStep {
141
147
  stubOnError?: StubPhaseResult;
142
148
  }
143
149
  export declare const TRACE_MAX_STEPS = 500;
150
+ /** Which stub file a live session wrote: before, after or on-error. */
144
151
  export type StubFileKind = "image" | "pdf" | "video";
145
152
  /**
146
153
  * Real, minimal, valid fixture files bundled at `assets/stubs/` - not
@@ -180,11 +187,13 @@ export interface ConsoleLogEntry {
180
187
  timestamp: string;
181
188
  }
182
189
  export declare const CONSOLE_LOG_MAX_ENTRIES = 200;
190
+ /** One service worker registration as reported by a live session. */
183
191
  export interface ServiceWorkerRegistrationInfo {
184
192
  scope: string;
185
193
  activeUrl?: string;
186
194
  state?: string;
187
195
  }
196
+ /** One cookie as reported by a live session's `auto cookies`. */
188
197
  export interface CookieInfo {
189
198
  name: string;
190
199
  value: string;
@@ -193,6 +202,7 @@ export interface CookieInfo {
193
202
  httpOnly: boolean;
194
203
  secure: boolean;
195
204
  }
205
+ /** Local and session storage of a live session's page. */
196
206
  export interface StorageSnapshot {
197
207
  localStorage: Record<string, string>;
198
208
  sessionStorage: Record<string, string>;
@@ -6,6 +6,7 @@
6
6
  * - otherwise -> bare token (flow export / checkpoint / block name) — caller decides
7
7
  */
8
8
  export type BlocksSelectKind = "regex" | "glob" | "bare";
9
+ /** A parsed `--blocks` selector: which Blocks, by name, glob or file, a command should use. */
9
10
  export interface BlocksSelect {
10
11
  kind: BlocksSelectKind;
11
12
  /** Original token. */
@@ -16,9 +17,11 @@ export interface BlocksSelect {
16
17
  }
17
18
  /** True when the token is file-select (glob/regex), not a bare flow/checkpoint name. */
18
19
  export declare function isFileSelectToken(token: string): boolean;
20
+ /** Parses a `--blocks` argument into a selector. */
19
21
  export declare function parseBlocksSelect(token: string): BlocksSelect;
20
22
  /** Glob → RegExp (simple: ** / * / ? only; no brace expansion). */
21
23
  export declare function globToRegExp(glob: string): RegExp;
24
+ /** True when a Block name and file match a parsed `--blocks` selector. */
22
25
  export declare function matchBlocksSelect(select: BlocksSelect, opts: {
23
26
  relFile: string;
24
27
  blockName?: string;
@@ -14,6 +14,7 @@ export function isFileSelectToken(token) {
14
14
  }
15
15
  return token.includes("*");
16
16
  }
17
+ /** Parses a `--blocks` argument into a selector. */
17
18
  export function parseBlocksSelect(token) {
18
19
  const raw = token.trim();
19
20
  if (raw.length >= 2 && raw.startsWith("/") && raw.endsWith("/")) {
@@ -52,6 +53,7 @@ export function globToRegExp(glob) {
52
53
  }
53
54
  return new RegExp("^" + out + "$");
54
55
  }
56
+ /** True when a Block name and file match a parsed `--blocks` selector. */
55
57
  export function matchBlocksSelect(select, opts) {
56
58
  const file = opts.relFile.replace(/\\/g, "/");
57
59
  const name = opts.blockName ?? "";
package/dist/config.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { PlaywrightTestConfig } from "@playwright/test";
2
2
  import type { ExtensionSpec } from "./extensions.js";
3
3
  import type { WebServerConfig } from "./webserver.js";
4
4
  import type { DemoPace } from "./highlights.js";
5
+ /** Where `--video` recordings are saved and at what size. */
5
6
  export interface VideoSettings {
6
7
  /** Where recordings are saved: absolute, `~/…`, or relative to the project. Default `~/Downloads/waygraph-videos/<project>` (the project's `.waygraph-videos/` where there is no Downloads folder, and on CI). */
7
8
  dir?: string;
@@ -40,6 +41,7 @@ export interface DemoSettings extends RunSettings {
40
41
  /** Shorter Next / auto-next gates; keeps the cursor and typing animation. */
41
42
  fast?: boolean;
42
43
  }
44
+ /** The project config in `config/waygraph.config.ts`: base URL, extensions, run and demo settings, web server and the Playwright block. */
43
45
  export interface WaygraphConfig {
44
46
  /** Same value `resolveBaseUrl` would otherwise read from package.json's `waygraph.baseUrl`. */
45
47
  baseUrl?: string;
@@ -10,6 +10,7 @@ export interface ApiCallResult {
10
10
  /** `response.json()` if the body parses as JSON, else the raw text (or `undefined` if neither). */
11
11
  body: unknown;
12
12
  }
13
+ /** Options for `defineApiBlock`: the HTTP call, how its result maps to a Checkpoint, and the demo network panel. */
13
14
  export interface ApiBlockOptions<In extends Checkpoint<string>, Out extends Checkpoint<string>> {
14
15
  name: string;
15
16
  description?: string;
@@ -24,9 +24,11 @@ export type MethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<st
24
24
  };
25
25
  /** @deprecated Prefer {@link MethodBlock} - same type; Action was the 0.7 name. */
26
26
  export type ActionBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = MethodBlock<In, Out>;
27
+ /** Builds a Block for one page action (fill, submit, click) that does not navigate. */
27
28
  export declare function defineMethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(base: Parameters<typeof defineBlock<In, Out>>[0]): MethodBlock<In, Out>;
28
29
  /** @deprecated Prefer {@link defineMethodBlock} - identical helper (0.7 name). */
29
30
  export declare const defineActionBlock: typeof defineMethodBlock;
31
+ /** Options for `defineAssertBlock`: a Checkpoint to stay on and the Traits that must hold. */
30
32
  export interface AssertBlockOptions<Out extends Checkpoint<string> = Checkpoint<string>> {
31
33
  name: string;
32
34
  description?: string;
@@ -1,6 +1,7 @@
1
1
  // Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
2
2
  import { checkpoint } from "../../types.js";
3
3
  import { defineBlock } from "../block.js";
4
+ /** Builds a Block for one page action (fill, submit, click) that does not navigate. */
4
5
  export function defineMethodBlock(base) {
5
6
  const built = defineBlock(base);
6
7
  Object.defineProperty(built, "__waygraphSalt", {
@@ -123,6 +123,7 @@ export type NavClickBlockOptions<Out extends Checkpoint<string>> = {
123
123
  highlights?: readonly WaygraphHighlight[] | ((out: Out) => readonly WaygraphHighlight[]);
124
124
  instanceOptions?: Block<Checkpoint<string>, Out>["instanceOptions"];
125
125
  };
126
+ /** A Block whose only action is clicking a link; built with `defineNavClickBlock`. */
126
127
  export type NavClickBlock<Out extends Checkpoint<string>> = NavBlock<Out>;
127
128
  /** @see {@link NavClickBlockOptions} */
128
129
  export declare function defineNavClickBlock<Out extends Checkpoint<string>>(options: NavClickBlockOptions<Out>): NavClickBlock<Out>;
@@ -4,6 +4,7 @@ import { MemPage } from "../../mem-page.js";
4
4
  import type { MemKey } from "../../mem-page.js";
5
5
  /** One Block (or lazy factory) registered on a {@link PageBlock}. */
6
6
  export type PageMethodEntry = DefinedBlock<any, any> | (() => DefinedBlock<any, any>);
7
+ /** Options for `definePageBlock`: the Checkpoint a page hub confirms and the Methods that hang off it. */
7
8
  export type PageBlockOptions<Out extends Checkpoint<string>> = {
8
9
  name: string;
9
10
  description?: string;
@@ -17,6 +17,7 @@ export declare function branchRoutes(flow: Flow<any>): ReadonlyMap<string, Flow<
17
17
  * `.branch()` continuations. Static - doesn't run anything.
18
18
  */
19
19
  export declare function collectBranchFlows(flow: Flow<any>): BranchEntry[];
20
+ /** The outcome of one branch path in a branch regression run. */
20
21
  export interface BranchRunResult {
21
22
  path: string;
22
23
  status: "ok" | "failed";
@@ -67,6 +67,7 @@ export interface FastForwardComposedBlock<In extends Checkpoint<string>, Out ext
67
67
  }
68
68
  /** True when `block` came from {@link fastForwardComposeBlock}. */
69
69
  export declare function isFastForwardBlock(block: Block<any, any>): block is FastForwardComposedBlock<any, any>;
70
+ /** Like `composeBlock`, but the steps run as one blitz-paced unit in a demo. */
70
71
  export declare function fastForwardComposeBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, Out>]): FastForwardComposedBlock<In, Out>;
71
72
  export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, Out>]): FastForwardComposedBlock<In, Out>;
72
73
  export declare function fastForwardComposeBlock<In extends Checkpoint<string>, B extends Checkpoint<string>, C extends Checkpoint<string>, Out extends Checkpoint<string>>(name: string, steps: readonly [Block<In, B>, Block<B, C>, Block<C, Out>]): FastForwardComposedBlock<In, Out>;
@@ -66,6 +66,7 @@ export interface BlockInfo {
66
66
  */
67
67
  block: Block<any, any>;
68
68
  }
69
+ /** A runnable chain of Blocks built by `engine.map()`. `run(mem)` launches its own browser; `run(context, mem)` reuses one. */
69
70
  export interface Flow<Out extends Checkpoint<string>> {
70
71
  /**
71
72
  * True once this Flow has been wrapped in {@link withSessionReset} - a
@@ -14,6 +14,7 @@ type S = Checkpoint<"__start__">;
14
14
  * defineFlow) - a real cycle check:structure forbids. This type is how that's avoided.
15
15
  */
16
16
  export type DefineFlowFn = (blocks: readonly [StartMarker, ...Block<any, any>[], EndMarker], options?: FlowOptions) => Flow<any>;
17
+ /** Per-step options for the map builder: `ff` fast-forwards the step, `pace` sets its demo pace. */
17
18
  export interface MapStepOpts {
18
19
  /**
19
20
  * Fast-forward just this step, inline - no `.ffStart()/.ffEnd()` bracket needed. Consecutive
@@ -29,6 +30,7 @@ export interface MapStepOpts {
29
30
  */
30
31
  pace?: DemoPace;
31
32
  }
33
+ /** Flow-level settings for `engine.map({ … })`: `memStub`, `sessionReset`, `expectedFailure`, `demoPace`, `highlightStyle`, `homeOrigin`. */
32
34
  export interface MapBuilderOptions {
33
35
  /**
34
36
  * This project's own origin (e.g. `"https://app.example.com"`) - enables
@@ -39,6 +41,11 @@ export interface MapBuilderOptions {
39
41
  homeOrigin?: string;
40
42
  /** Fill missing `requires` keys from `registerMemStub` when the flow runs (what `withMemStub` did). */
41
43
  memStub?: boolean;
44
+ /**
45
+ * This flow wants a fresh browser session (cookies and storage cleared) when it runs after another one, in a CLI chain
46
+ * (`waygraph run "a then b"`) or nested with `.flow(sub)`: a second user signing in, a logged-out check.
47
+ */
48
+ sessionReset?: boolean;
42
49
  /** Marks a flow that is supposed to throw, with the reason shown in the demo (what `withExpectedFailure` did). */
43
50
  expectedFailure?: string;
44
51
  /** Default demo pace for the whole flow (what `withDemoPace` did). */
@@ -48,7 +55,7 @@ export interface MapBuilderOptions {
48
55
  }
49
56
  /** What `.flow()` takes for the sub-flow it runs inline. */
50
57
  export interface MapFlowOpts {
51
- /** Clear cookies and storage right before the sub-flow, e.g. to start a second user fresh (what `withSessionReset` + `chainFlow` did). */
58
+ /** Clear cookies and storage right before the sub-flow, e.g. to start a second user fresh. Defaults to the sub-flow's own `sessionReset`. */
52
59
  reset?: boolean;
53
60
  }
54
61
  /**
@@ -308,7 +308,7 @@ export class MapBuilder {
308
308
  flow(sub, opts) {
309
309
  let next = this;
310
310
  sub.blocks().forEach((info, i) => {
311
- const block = i === 0 && opts?.reset ? resetBefore(info.block) : info.block;
311
+ const block = i === 0 && (opts?.reset ?? sub.resetSession) ? resetBefore(info.block) : info.block;
312
312
  next = next.appendStep(block);
313
313
  });
314
314
  return next;
@@ -36,6 +36,7 @@ export interface Layout {
36
36
  /** Function form gets the full resolved Checkpoint, same shape `runVerify`/a Block's own `verify` already use - not just the tag. */
37
37
  verify: Trait[] | ((out: Checkpoint<string>) => Trait[]);
38
38
  }
39
+ /** Options for `defineLayout`: which Checkpoints it applies to and the Traits it enforces. */
39
40
  export interface LayoutOptions {
40
41
  name: string;
41
42
  description?: string;
@@ -142,6 +143,7 @@ export declare function spawnTab<TOut extends Checkpoint<string>>(entry: Block<C
142
143
  export declare function narrate<T>(locator: Locator, caption: string, action: () => Promise<T>): Promise<T>;
143
144
  /** Reserved markers bookending a `defineFlow([start, ...blocks, end])` call. */
144
145
  export declare const start: unique symbol;
146
+ /** Marks the end of a hand-built chain. Only the deprecated `defineFlow` needs it; `map()` does not. */
145
147
  export declare const end: unique symbol;
146
148
  export type StartMarker = typeof start;
147
149
  export type EndMarker = typeof end;
@@ -219,4 +219,5 @@ export async function narrate(locator, caption, action) {
219
219
  }
220
220
  /** Reserved markers bookending a `defineFlow([start, ...blocks, end])` call. */
221
221
  export const start = Symbol("waygraph.start");
222
+ /** Marks the end of a hand-built chain. Only the deprecated `defineFlow` needs it; `map()` does not. */
222
223
  export const end = Symbol("waygraph.end");
package/dist/errors.d.ts CHANGED
@@ -148,6 +148,7 @@ export declare const MSG_FASTFORWARD_EMPTY: (name: string) => string;
148
148
  export declare const MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_INDEX: (index: number, count: number) => string;
149
149
  export declare const MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_NAME: (blockName: string) => string;
150
150
  export declare const MSG_CHAINFLOW_EMPTY = "chainFlow: give at least one Flow";
151
+ /** The code of a `WaygraphError`, e.g. `WG_PREFLIGHT_MISSING_KEY`. */
151
152
  export type WaygraphErrorCode = keyof typeof WAYGRAPH_ERRORS;
152
153
  /** A thrown engine error with a stable, greppable `.code` - see WAYGRAPH_ERRORS for the full list. */
153
154
  export declare class WaygraphError extends Error {
@@ -4,6 +4,7 @@ export type ExtensionSpec = string | {
4
4
  path?: string;
5
5
  sha256?: string;
6
6
  };
7
+ /** Names accepted in `extensions: [...]` mapped to their Chrome Web Store ids. */
7
8
  export declare const KNOWN_EXTENSIONS: Readonly<Record<string, string>>;
8
9
  /** Unpacks a .crx and pins the manifest `key`, so the extension keeps its store id (its origin is then stable, e.g. for an API allowlist). */
9
10
  export declare function unpackCrx(crx: Buffer, dest: string): void;
@@ -4,6 +4,7 @@ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join, resolve, sep } from "node:path";
6
6
  import { inflateRawSync } from "node:zlib";
7
+ /** Names accepted in `extensions: [...]` mapped to their Chrome Web Store ids. */
7
8
  export const KNOWN_EXTENSIONS = {
8
9
  hoppscotch: "amknoiejhlmhancpahfcfcfhllgkpbld",
9
10
  };
@@ -9,11 +9,15 @@ export declare const FIXTURE_DURATION_SLOW_MS_DEFAULT = 4000;
9
9
  export declare const SLIDE_DURATION_MS_DEFAULT = 2000;
10
10
  /** @deprecated Prefer FIXTURE_DURATION_FAST_MS_DEFAULT */
11
11
  export declare const SLIDE_DURATION_FAST_MS_DEFAULT = 600;
12
+ /** Turns any accepted pace spelling into a `DemoPace`; unknown values mean normal. */
12
13
  export declare function normalizeDemoPace(raw: unknown): DemoPace;
14
+ /** The multiplier a pace applies to dwell and gate time (1 = normal); `demo.speeds` redefines the named ones. */
13
15
  export declare function demoPaceScale(pace: DemoPace): number;
16
+ /** True when a pace is blitz: no cursor, ring pop or typing animation. */
14
17
  export declare function demoPaceIsBlitz(pace: DemoPace): boolean;
15
18
  /** True when pace should use the short-gate / fast fixture path (not slow authored). */
16
19
  export declare function demoPaceIsFast(pace: DemoPace): boolean;
20
+ /** True when a pace lengthens dwell and gates. */
17
21
  export declare function demoPaceIsSlow(pace: DemoPace): boolean;
18
22
  /** Autoplay / Next-gate ms for this pace (base is WAYGRAPH_AUTOPLAY_MS or 1800). */
19
23
  export declare function demoPaceGateMs(pace: DemoPace, baseAutoplayMs: number): number;
@@ -8,6 +8,7 @@ export const FIXTURE_DURATION_SLOW_MS_DEFAULT = 4000;
8
8
  export const SLIDE_DURATION_MS_DEFAULT = FIXTURE_DURATION_MS_DEFAULT;
9
9
  /** @deprecated Prefer FIXTURE_DURATION_FAST_MS_DEFAULT */
10
10
  export const SLIDE_DURATION_FAST_MS_DEFAULT = FIXTURE_DURATION_FAST_MS_DEFAULT;
11
+ /** Turns any accepted pace spelling into a `DemoPace`; unknown values mean normal. */
11
12
  export function normalizeDemoPace(raw) {
12
13
  if (typeof raw === "number" && Number.isFinite(raw) && raw > 0)
13
14
  return raw;
@@ -52,6 +53,7 @@ function paceSpeeds() {
52
53
  }
53
54
  return out;
54
55
  }
56
+ /** The multiplier a pace applies to dwell and gate time (1 = normal); `demo.speeds` redefines the named ones. */
55
57
  export function demoPaceScale(pace) {
56
58
  if (typeof pace === "number") {
57
59
  if (pace > 20)
@@ -66,6 +68,7 @@ export function demoPaceScale(pace) {
66
68
  return paceSpeeds().slow;
67
69
  return 1;
68
70
  }
71
+ /** True when a pace is blitz: no cursor, ring pop or typing animation. */
69
72
  export function demoPaceIsBlitz(pace) {
70
73
  return pace === "blitz" || (typeof pace === "number" && pace > 0 && pace <= 0.1);
71
74
  }
@@ -79,6 +82,7 @@ export function demoPaceIsFast(pace) {
79
82
  return pace < 0.75;
80
83
  return false;
81
84
  }
85
+ /** True when a pace lengthens dwell and gates. */
82
86
  export function demoPaceIsSlow(pace) {
83
87
  if (pace === "slow")
84
88
  return true;
@@ -3,7 +3,9 @@ import type { DeviceOrientation, DevicePreset, DeviceState, DeviceViewport } fro
3
3
  export declare const DEVICE_PRESETS: Record<DevicePreset, Omit<DeviceState, "touchMode"> & {
4
4
  touchMode?: boolean;
5
5
  }>;
6
+ /** Turns a device name (`mobile`, `tablet`, ...) into a known preset. */
6
7
  export declare function normalizeDevicePreset(raw: unknown): DevicePreset | undefined;
8
+ /** Turns `portrait` / `landscape` spellings into a device orientation. */
7
9
  export declare function normalizeDeviceOrientation(raw: unknown): DeviceOrientation | undefined;
8
10
  /** Infer orientation from box (square counts as landscape). */
9
11
  export declare function orientationFromViewport(vp: DeviceViewport): DeviceOrientation;
@@ -25,6 +25,7 @@ export const DEVICE_PRESETS = {
25
25
  orientation: "landscape",
26
26
  },
27
27
  };
28
+ /** Turns a device name (`mobile`, `tablet`, ...) into a known preset. */
28
29
  export function normalizeDevicePreset(raw) {
29
30
  const s = String(raw ?? "")
30
31
  .trim()
@@ -37,6 +38,7 @@ export function normalizeDevicePreset(raw) {
37
38
  return "desktop";
38
39
  return undefined;
39
40
  }
41
+ /** Turns `portrait` / `landscape` spellings into a device orientation. */
40
42
  export function normalizeDeviceOrientation(raw) {
41
43
  const s = String(raw ?? "")
42
44
  .trim()
@@ -33,6 +33,7 @@ export type WaygraphTodoItem = {
33
33
  /** Explicit current. If omitted, derived from todoIndex (index === todoIndex). */
34
34
  current?: boolean;
35
35
  };
36
+ /** One todo item as authored: a string or `{ id, text, done }`. */
36
37
  export type WaygraphTodoInput = string | WaygraphTodoItem;
37
38
  /**
38
39
  * Dock list presentation:
@@ -69,6 +70,7 @@ export type WaygraphTodoGroupInput = {
69
70
  /** Sequential only: which item is current (0-based). */
70
71
  todoIndex?: number;
71
72
  };
73
+ /** A titled checklist in the demo todo dock. */
72
74
  export type WaygraphTodoGroup = {
73
75
  id?: string;
74
76
  title?: string;
@@ -300,6 +302,7 @@ export interface WaygraphHighlightStub extends FixtureDurationFields {
300
302
  }
301
303
  /** Flow fixture patch: label required; selector optional (inherits from stub). */
302
304
  export type WaygraphHighlightFixture = Partial<Pick<WaygraphHighlightStub, "selector">> & Required<Pick<WaygraphHighlightStub, "label">> & Pick<WaygraphHighlightStub, "detail" | "tag" | "tone" | "size" | "weight" | "zoom" | "zoomOut" | "focus" | "followMouse" | "follow" | "color" | "cursor" | "todo" | "gesture"> & FixtureDurationFields;
305
+ /** A static stub phase: named ring slots to paint before or after a step. */
303
306
  export type HighlightStubPhase = Record<string, WaygraphHighlightStub>;
304
307
  /**
305
308
  * Open stub lifecycle context. Authors set rings + episode fixtures freely —
@@ -459,6 +462,7 @@ export type StubCtx<Out extends Checkpoint<string> = Checkpoint<string>> = {
459
462
  highlights?: HighlightStubPhase;
460
463
  } & StubPhaseFixtures): void;
461
464
  };
465
+ /** A stub callback: receives the stub `ctx` and paints rings, titles and todos. */
462
466
  export type StubLifecycleFn<Out extends Checkpoint<string>> = (ctx: StubCtx<Out>) => void | HighlightStubPhase | Promise<void | HighlightStubPhase>;
463
467
  /**
464
468
  * Block stub authoring:
@@ -551,6 +555,7 @@ export type HighlightStyleDefaults = {
551
555
  * absolute gate/dwell ms when `> 20` (e.g. `4500`)
552
556
  */
553
557
  export type DemoPaceName = "blitz" | "fast" | "normal" | "slow";
558
+ /** How fast a demo step runs: `"fast"`, `"slow"`, `"blitz"`, `"normal"`, or a multiplier (`0.5`, `2`). */
554
559
  export type DemoPace = DemoPaceName | number;
555
560
  export type WaygraphSlidesOrFn<Out extends Checkpoint<string>> = readonly WaygraphSlide[] | ((out: Out) => readonly WaygraphSlide[]);
556
561
  /** Demo stub phase names (block instruction + flow fixtures). */
@@ -570,6 +575,7 @@ export interface WaygraphHighlight {
570
575
  label: string;
571
576
  tone?: HighlightTone;
572
577
  }
578
+ /** A ring or caption after its defaults and overrides are merged, ready to paint. */
573
579
  export type ResolvedHighlight = WaygraphHighlightStub;
574
580
  export type StubBagState = {
575
581
  highlights: HighlightStubPhase;
@@ -1,3 +1,4 @@
1
+ import { getMemStub } from "../mem-stub.js";
1
2
  import { createInterface } from "node:readline/promises";
2
3
  import { ensureShadowRoot } from "../ui/shadow.js";
3
4
  import { stdin as input, stdout as output } from "node:process";
@@ -115,6 +116,11 @@ export function seedDefaultMem(library, mem) {
115
116
  mem.set(k, envParsed[k.name]);
116
117
  continue;
117
118
  }
119
+ const stub = getMemStub(k);
120
+ if (stub) {
121
+ mem.set(k, stub());
122
+ continue;
123
+ }
118
124
  const def = defaultMemValueForKey(k.name);
119
125
  if (def !== undefined)
120
126
  mem.set(k, def);
@@ -10,11 +10,17 @@
10
10
  * `assertWgOverlayReady(page)` (or WAYGRAPH_PROVE_EXIT=1) passes.
11
11
  */
12
12
  import type { Page } from "@playwright/test";
13
+ /** Selector matching every element waygraph's overlay draws into a page. */
13
14
  export declare const WG_UI_SEL = "[data-wg-ui=\"1\"]";
15
+ /** Selector of the overlay element that appears when the step panel is ready. */
14
16
  export declare const WG_READY_PANEL_SEL = "[data-wg-modal=\"panel\"][data-wg-ready=\"1\"]";
17
+ /** Selector of the overlay element that appears when the auto panel is ready. */
15
18
  export declare const WG_READY_AUTO_SEL = "[data-wg-modal=\"auto-panel\"][data-wg-ready=\"1\"]";
19
+ /** Selector of the overlay element that appears when the banner is ready. */
16
20
  export declare const WG_READY_BANNER_SEL = "[data-wg-modal=\"banner\"][data-wg-ready=\"1\"]";
21
+ /** The kind of modal the overlay beacon reports. */
17
22
  export type WgModalKind = "panel" | "banner" | "auto-panel";
23
+ /** One overlay element a session reports through its beacon. */
18
24
  export type WgBeaconRow = {
19
25
  id: string | null;
20
26
  modal: string | null;
@@ -31,6 +37,7 @@ export type WgBeaconRow = {
31
37
  };
32
38
  /** Browser-side beacon reader (also installed as window.__wgOverlayBeacon). */
33
39
  export declare function readWgOverlayBeaconInPage(): WgBeaconRow[];
40
+ /** Reads the overlay beacon from a page: what waygraph's own UI is showing. */
34
41
  export declare function readWgOverlayBeacon(page: Page): Promise<WgBeaconRow[]>;
35
42
  /**
36
43
  * Hard gate: a blank / missing / opacity-0 modal fails.
@@ -9,9 +9,13 @@
9
9
  * Agents: do not claim the stepper works unless
10
10
  * `assertWgOverlayReady(page)` (or WAYGRAPH_PROVE_EXIT=1) passes.
11
11
  */
12
+ /** Selector matching every element waygraph's overlay draws into a page. */
12
13
  export const WG_UI_SEL = '[data-wg-ui="1"]';
14
+ /** Selector of the overlay element that appears when the step panel is ready. */
13
15
  export const WG_READY_PANEL_SEL = '[data-wg-modal="panel"][data-wg-ready="1"]';
16
+ /** Selector of the overlay element that appears when the auto panel is ready. */
14
17
  export const WG_READY_AUTO_SEL = '[data-wg-modal="auto-panel"][data-wg-ready="1"]';
18
+ /** Selector of the overlay element that appears when the banner is ready. */
15
19
  export const WG_READY_BANNER_SEL = '[data-wg-modal="banner"][data-wg-ready="1"]';
16
20
  /** Browser-side beacon reader (also installed as window.__wgOverlayBeacon). */
17
21
  export function readWgOverlayBeaconInPage() {
@@ -37,6 +41,7 @@ export function readWgOverlayBeaconInPage() {
37
41
  };
38
42
  });
39
43
  }
44
+ /** Reads the overlay beacon from a page: what waygraph's own UI is showing. */
40
45
  export async function readWgOverlayBeacon(page) {
41
46
  return page.evaluate(() => {
42
47
  const w = window;
@@ -31,6 +31,7 @@
31
31
  import { type WaygraphGraph } from "../analysis/graph.js";
32
32
  import { type BrowserStartInit } from "./browser.js";
33
33
  import type { SessionSnapshot } from "../auto-session.js";
34
+ /** What `pilotStart` returns: the session id, socket path and first snapshot. */
34
35
  export interface PilotStartResult {
35
36
  sessionId: string;
36
37
  socketPath: string;
@@ -1,3 +1,4 @@
1
+ /** The edge-coverage report `traverse` writes: which graph edges were walked. */
1
2
  export interface TraverseCoverageReport {
2
3
  version: 1;
3
4
  generatedAt: string;
@@ -41,6 +42,7 @@ export declare function normalizeHitKey(hitKey: string, graphKeys: ReadonlySet<s
41
42
  * Returns 0-1 fraction, or null when unset/invalid.
42
43
  */
43
44
  export declare function parseMinEdgeCoverage(raw: unknown): number | null;
45
+ /** Builds the `traverse` coverage report from the edges walked and the graph's edges. */
44
46
  export declare function buildCoverageReport(opts: {
45
47
  projectDir: string;
46
48
  parallel: number;
@@ -51,5 +53,7 @@ export declare function buildCoverageReport(opts: {
51
53
  }): TraverseCoverageReport;
52
54
  /** Greppable one-liner for agents/CI. */
53
55
  export declare function formatCoverageLine(report: TraverseCoverageReport): string;
56
+ /** Where `traverse` writes its coverage report by default. */
54
57
  export declare function defaultCoverageOutPath(projectDir: string): string;
58
+ /** Writes the `traverse` coverage report to disk. */
55
59
  export declare function writeCoverageReport(path: string, report: TraverseCoverageReport): void;
@@ -68,6 +68,7 @@ export function parseMinEdgeCoverage(raw) {
68
68
  return n / 100;
69
69
  return null;
70
70
  }
71
+ /** Builds the `traverse` coverage report from the edges walked and the graph's edges. */
71
72
  export function buildCoverageReport(opts) {
72
73
  const all = [...new Set(opts.allEdgeKeys)].sort();
73
74
  const graphSet = new Set(all);
@@ -118,9 +119,11 @@ export function formatCoverageLine(report) {
118
119
  : "";
119
120
  return `[Coverage edges=${report.edgesHit}/${report.edgesTotal} ratio=${pct}%${minPart}]`;
120
121
  }
122
+ /** Where `traverse` writes its coverage report by default. */
121
123
  export function defaultCoverageOutPath(projectDir) {
122
124
  return join(projectDir, ".waygraph-traverse", "coverage.json");
123
125
  }
126
+ /** Writes the `traverse` coverage report to disk. */
124
127
  export function writeCoverageReport(path, report) {
125
128
  mkdirSync(dirname(path), { recursive: true });
126
129
  writeFileSync(path, JSON.stringify(report, null, 2) + "\n", "utf-8");
@@ -2,6 +2,7 @@ export interface EdgeLeaseRecord {
2
2
  workerId: string;
3
3
  claimedAt: number;
4
4
  }
5
+ /** Hands out graph edges to parallel `traverse` workers so no two workers walk the same edge. */
5
6
  export declare class EdgeLeaseCoordinator {
6
7
  private readonly held;
7
8
  private readonly dir;
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
7
7
  import { join } from "node:path";
8
+ /** Hands out graph edges to parallel `traverse` workers so no two workers walk the same edge. */
8
9
  export class EdgeLeaseCoordinator {
9
10
  held = new Map();
10
11
  dir;
@@ -1,10 +1,13 @@
1
+ /** How `traverse` workers share a browser: one session, or a clone per worker. */
1
2
  export type TraverseSessionMode = "clone" | "inherit";
3
+ /** What one `traverse` worker did: edges walked and failures. */
2
4
  export interface TraverseWorkerResult {
3
5
  exitCode: number;
4
6
  steps: number;
5
7
  edgesHit: string[];
6
8
  leaf?: string;
7
9
  }
10
+ /** Options for `runTraverse`: workers, session mode, step limit, coverage gate. */
8
11
  export interface TraverseOptions {
9
12
  baseURL?: string;
10
13
  startUrl?: string;
@@ -13,7 +13,7 @@ const homeOrigin = process.env.WAYGRAPH_BASE_URL || "http://127.0.0.1:4277";
13
13
  /**
14
14
  * Same real Blocks, same real Checkpoints, same real fixture server as
15
15
  * routed-demo.flow.ts - built with `engine.map()` instead of
16
- * `engine.defineFlow([start, ..., end])` to prove the fluent builder
16
+ * the deprecated `engine.defineFlow([start, ..., end])` to prove the fluent builder
17
17
  * against a real browser/DOM, not just the in-memory fakes
18
18
  * tests/nav/map-builder.spec.ts already covers in the main package.
19
19
  *
@@ -1,4 +1,4 @@
1
- import { Engine, start, end } from "waygraph";
1
+ import { Engine } from "waygraph";
2
2
  import { NavDashboardBlock } from "../map/(app_base)/dashboard/_nav.block.js";
3
3
  import { ClickWidgetBlock } from "../map/(app_base)/dashboard/_methods/click-widget.block.js";
4
4
  import { NavDocsBlock } from "../map/(external)/docs/_nav.block.js";
@@ -9,4 +9,4 @@ import "../map/(external)/docs/_page.block.js";
9
9
  const engine = new Engine();
10
10
 
11
11
  /** Smoke: dashboard -> click widget -> docs, all Blocks under the Waygraph Map folder convention. */
12
- export const routedDemoFlow = engine.defineFlow([start, NavDashboardBlock, ClickWidgetBlock, NavDocsBlock, end]);
12
+ export const routedDemoFlow = engine.map().start().gotoPage(NavDashboardBlock).method(ClickWidgetBlock).gotoPage(NavDocsBlock).end();