waygraph 0.15.9 → 0.15.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
@@ -920,6 +920,7 @@ really a Nav/Page/Assert/Method from this package's own factories.
920
920
  | Interactive explore (Add/Remove/Open details from live page) | `cd examples/saucedemo && npm i && npx waygraph auto` |
921
921
  | Scaffold a new **offline** project (green `npm test` on local fixture `:4177`) | `npx create-waygraph my-app` **or** `npx waygraph init my-app` |
922
922
  | Install coding-agent defs for diving an app into Blocks | `npx waygraph agent-dive --loop claude` (also `opencode` / `cursor` / `vscode`) |
923
+ | Print a packaged agent skill to stdout | `npx waygraph --skill` (list) / `--skill-pilot` / `--skill-pilot-blind` / `--skill-convention` |
923
924
  | Add waygraph to an existing repo | `npm install waygraph @playwright/test` |
924
925
 
925
926
  **Scaffold is not hidden inside waygraph alone** - the offline starter also ships as
@@ -1034,6 +1035,7 @@ Flows are files (0.10.5+):
1034
1035
  | Waygraph Map enforcement (verbatim url-vs-folder, exits 1 on a violation) | `waygraph map [project]` |
1035
1036
  | Graph crawl | `waygraph traverse [project] --parallel N --min-edge-coverage 80%` |
1036
1037
  | Coding-agent defs | `waygraph agent-dive --loop claude` |
1038
+ | Print packaged skills | `waygraph --skill` / `--skill-pilot` / `--skill-pilot-blind` / `--skill-convention` |
1037
1039
  | One-shot temp-dir demo | `waygraph try demo` / `waygraph try auto` / `waygraph try auto:cli` |
1038
1040
 
1039
1041
  `--blocks` / positional accepts a Flow export, a `.flow.ts` path, or `"a then b"`.
@@ -19,6 +19,17 @@ export declare function loadAgentSpecs(): AgentSpec[];
19
19
  * body frontmatter shape `parseAgentSpec` already parses.
20
20
  */
21
21
  export declare function loadSkillSpecs(): AgentSpec[];
22
+ /** CLI flag -> packaged skill file stem (under templates/skills/). */
23
+ export declare const SKILL_FLAG_MAP: {
24
+ readonly "--skill-pilot": "waygraph-pilot";
25
+ readonly "--skill-pilot-blind": "waygraph-blind-pilot";
26
+ readonly "--skill-convention": "waygraph-convention";
27
+ };
28
+ export type SkillFlag = keyof typeof SKILL_FLAG_MAP;
29
+ /** Raw skill markdown (frontmatter + body), as shipped in the package. */
30
+ export declare function readSkillMarkdown(stem: string): string;
31
+ /** Print `--skill` index (available flags + one-line descriptions). */
32
+ export declare function printSkillIndex(): void;
22
33
  export interface AgentDiveOptions {
23
34
  loop: AgentDiveLoop;
24
35
  projectDir: string;
@@ -85,6 +85,34 @@ export function loadSkillSpecs() {
85
85
  .sort()
86
86
  .map((f) => parseAgentSpec(join(dir, f)));
87
87
  }
88
+ /** CLI flag -> packaged skill file stem (under templates/skills/). */
89
+ export const SKILL_FLAG_MAP = {
90
+ "--skill-pilot": "waygraph-pilot",
91
+ "--skill-pilot-blind": "waygraph-blind-pilot",
92
+ "--skill-convention": "waygraph-convention",
93
+ };
94
+ /** Raw skill markdown (frontmatter + body), as shipped in the package. */
95
+ export function readSkillMarkdown(stem) {
96
+ const path = join(skillsTemplateDir(), `${stem}.skill.md`);
97
+ if (!existsSync(path)) {
98
+ throw new Error(`waygraph: skill template missing at ${path}`);
99
+ }
100
+ const raw = readFileSync(path, "utf-8");
101
+ return raw.endsWith("\n") ? raw : raw + "\n";
102
+ }
103
+ /** Print `--skill` index (available flags + one-line descriptions). */
104
+ export function printSkillIndex() {
105
+ const skills = loadSkillSpecs();
106
+ const byName = new Map(skills.map((s) => [s.name, s]));
107
+ console.log("waygraph skills (print full text with the matching flag):\n");
108
+ for (const [flag, stem] of Object.entries(SKILL_FLAG_MAP)) {
109
+ const spec = byName.get(stem);
110
+ const desc = spec?.description ?? stem;
111
+ console.log(` npx waygraph ${flag}`);
112
+ console.log(` ${desc}\n`);
113
+ }
114
+ console.log("Also: npx waygraph agent-dive --loop claude # write .claude/skills/*/SKILL.md");
115
+ }
88
116
  function writeFileLogged(path, content, kind) {
89
117
  mkdirSync(dirname(path), { recursive: true });
90
118
  writeFileSync(path, content.endsWith("\n") ? content : content + "\n");
package/dist/cli.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  * run Execute; `--blocks` `--data` `--non-headless` `--video`
9
9
  *
10
10
  * Also: list / nav / validate / check / graph / init / agent-dive / traverse / try
11
+ * Skills: --skill / --skill-pilot / --skill-pilot-blind / --skill-convention
11
12
  * Aliases (one release): `chain` -> run/demo --blocks; `--autoplay` -> `--auto-next`
12
13
  *
13
14
  * "project" defaults to cwd. Flags beat WAYGRAPH_* env.
package/dist/cli.js CHANGED
@@ -8,6 +8,7 @@
8
8
  * run Execute; `--blocks` `--data` `--non-headless` `--video`
9
9
  *
10
10
  * Also: list / nav / validate / check / graph / init / agent-dive / traverse / try
11
+ * Skills: --skill / --skill-pilot / --skill-pilot-blind / --skill-convention
11
12
  * Aliases (one release): `chain` -> run/demo --blocks; `--autoplay` -> `--auto-next`
12
13
  *
13
14
  * "project" defaults to cwd. Flags beat WAYGRAPH_* env.
@@ -22,7 +23,7 @@ import { checkMap } from "./map-check.js";
22
23
  import { runAutoExplore } from "./auto-explore-run.js";
23
24
  import { pilotStart } from "./pilot.js";
24
25
  import { spawnDetachedSession, requestSession, runAttachLoop, runAutoServeCommand, } from "./auto-session-ipc.js";
25
- import { runAgentDive } from "./agent-dive.js";
26
+ import { runAgentDive, printSkillIndex, readSkillMarkdown, SKILL_FLAG_MAP, } from "./agent-dive.js";
26
27
  import { runTraverse } from "./traverse-run.js";
27
28
  import { parseMinEdgeCoverage } from "./traverse-coverage.js";
28
29
  import { isFileSelectToken, parseBlocksSelect, } from "./blocks-select.js";
@@ -7266,6 +7267,12 @@ Also:
7266
7267
  try auto:cli / --cli Terminal menu instead
7267
7268
  try auto --headed Same as try auto (compat)
7268
7269
 
7270
+ Skills (print packaged skill markdown to stdout - for agents / paste):
7271
+ waygraph --skill List available skills
7272
+ waygraph --skill-pilot Drive an existing Block graph
7273
+ waygraph --skill-pilot-blind Cold-start: raw ops + author Blocks
7274
+ waygraph --skill-convention Block/Map authoring conventions
7275
+
7269
7276
  Examples:
7270
7277
  waygraph list # file → export map
7271
7278
  waygraph run src/flows/shop.flow.ts --data '{...}'
@@ -7295,6 +7302,15 @@ async function main() {
7295
7302
  if (!command || command === "--help" || command === "-h") {
7296
7303
  usage();
7297
7304
  }
7305
+ if (command === "--skill") {
7306
+ printSkillIndex();
7307
+ process.exit(0);
7308
+ }
7309
+ if (command && command in SKILL_FLAG_MAP) {
7310
+ const stem = SKILL_FLAG_MAP[command];
7311
+ process.stdout.write(readSkillMarkdown(stem));
7312
+ process.exit(0);
7313
+ }
7298
7314
  switch (command) {
7299
7315
  case "list": {
7300
7316
  const proj = resolve(args[1] ?? process.cwd());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.15.9",
3
+ "version": "0.15.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",
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: waygraph-convention
3
+ description: Author or review waygraph Blocks/Flows under the consumer + Waygraph Map conventions - use when writing new Blocks, migrating folder layout, or answering "how should this project be organized," not when driving an already-built session (use waygraph-pilot / waygraph-blind-pilot for that).
4
+ ---
5
+
6
+ Waygraph convention is how Blocks are *shaped and placed*, not how a live session is
7
+ driven. Print this skill, then write or rearrange files so `waygraph check` / `waygraph map`
8
+ stay clean. For operating an existing graph, use `--skill-pilot`. For cold-start authoring
9
+ against a live site, use `--skill-pilot-blind`.
10
+
11
+ ## Hard rules (not style preferences)
12
+
13
+ 1. **One distinct action per Block.** Fill and submit are two Blocks. A login form is
14
+ `fill-username` (self-loop) + `fill-password` (self-loop) + `submit-login` (transition),
15
+ never one Method that "fills and logs in." Same split for checkout fields. Canonical
16
+ shape: `examples/saucedemo/src/blocks/saucedemo-web/methods/`.
17
+ 2. **Navigation only inside Nav.** `page.goto` / NavBlock `click` live in
18
+ `defineNavBlock` / `defineNavClickBlock` only. Method/Effect `act` uses ActionPage
19
+ (no goto) even when the app changes URL as a side effect of a button click.
20
+ 3. **Selectors in `*Sel`, never inline.** DOM strings live in a `*Sel` next to the page
21
+ (static + `(id) => …`). Mem keys store values, not selectors. `waygraph check` warns on
22
+ inline selector literals in `Trait.visible` / `Trait.text`.
23
+ 4. **Assert-only = `defineAssertBlock`.** Self-loop, no hand-written `act`/`resolve`. Pass
24
+ an explicit type argument when it sits between two specifically-typed Blocks in a Flow.
25
+ 5. **`requires` = externally supplied.** A key an earlier Block in the same chain produces
26
+ is never listed under `requires` - preflight checks the whole chain up front.
27
+
28
+ ## Block kinds (file convention)
29
+
30
+ | Kind | File | Helper | `page.goto`? |
31
+ |------|------|--------|--------------|
32
+ | Page | `*.page.block.ts` / `_page.block.ts` | `definePageBlock` | Optional deep-link |
33
+ | Nav | `nav-*.block.ts` / `_nav.block.ts` | `defineNavBlock` / `defineNavClickBlock` | Yes (`url` XOR `click`) |
34
+ | Effect | `*.effect.block.ts` in `methods/` / `_methods/` | `defineEffectBlock` | No |
35
+ | Method | `*.method.block.ts` in `methods/` / `_methods/` | `defineMethodBlock` | No |
36
+ | Assert | with Method/Effect peers | `defineAssertBlock` | No |
37
+
38
+ Effects that appear in `waygraph auto` menus need `instanceOptions` that scan the live DOM
39
+ (or mem) for labeled rows.
40
+
41
+ ## Two layouts (same Block kinds)
42
+
43
+ **Freeform ("manual mode")** - still valid; real consumers depend on it:
44
+
45
+ ```text
46
+ src/blocks/<site>/ # THIS FOLDER IS URL "/"
47
+ nav-login.block.ts
48
+ methods/fill-username.method.block.ts
49
+ inventory/ # /inventory.html
50
+ inventory.page.block.ts
51
+ methods/add-to-cart.effect.block.ts
52
+ ```
53
+
54
+ Folders mirror real app routes (Next.js `app/` page routes). Do **not** invent parallel
55
+ families like `root/`, `landing/`, or `shell/nav/` that are not real URLs. `/` lives at the
56
+ namespace root.
57
+
58
+ **Waygraph Map** - forced convention when `src/map/` exists:
59
+
60
+ ```text
61
+ src/map/
62
+ (app_base)/ # organizational group only - never part of a Checkpoint tag
63
+ dashboard/ # must verbatim-match the real URL path (/dashboard)
64
+ _page.block.ts
65
+ _nav.block.ts
66
+ _sel.ts
67
+ _methods/click-widget.block.ts
68
+ (external)/ # cross-origin (mailpit, etc.) - same shape
69
+ docs/
70
+ _page.block.ts
71
+ _nav.block.ts
72
+ _sel.ts
73
+ ```
74
+
75
+ - `(group)` parentheses and leading-underscore segments (`_methods/`, `_page…`) are
76
+ **not** URL segments. `waygraph map` excludes them when checking folder-vs-URL.
77
+ - A bare non-underscore folder always means a real child Checkpoint/URL segment.
78
+ - Prefer `map()` over a hand-assembled `defineFlow([start, ...])` when wiring Map Blocks -
79
+ it rejects Blocks that didn't come from a real factory (no silent teleporting).
80
+
81
+ Mail / external tools: under `*-external/<tool>/` or `map/(external)/<tool>/`, never under
82
+ the site's `*-web/` tree. Browser-driven (DOM / iframe Traits), not the catcher's REST API.
83
+
84
+ ## Verify before you call it done
85
+
86
+ ```bash
87
+ npx waygraph check . # orphans + nav-escape + inline-selector warnings
88
+ npx waygraph map . # exit 1 if src/map/ folder path != real static url
89
+ npx waygraph validate . # every .flow.ts loads
90
+ npx waygraph graph . # nodes/edges/skipped/orphans - counts should make sense
91
+ npm run typecheck # when the consumer has it
92
+ ```
93
+
94
+ `waygraph check` should report zero nav warnings. Orphan Blocks (not in any `.flow.ts`)
95
+ are still runnable in Pilot's live menu - orphan status only blocks
96
+ `auto --blocks <From> <To>` pathfinding.
97
+
98
+ ## Related skills (print via CLI)
99
+
100
+ ```bash
101
+ npx waygraph --skill # list
102
+ npx waygraph --skill-pilot # drive an existing Block graph
103
+ npx waygraph --skill-pilot-blind # cold-start: raw ops + author Blocks as you go
104
+ npx waygraph --skill-convention # this file
105
+ ```
106
+
107
+ Worked freeform example: `examples/saucedemo/docs/CONVENTION.md`.
108
+ Map design history: `openspec/changes/waygraph-map/`.
109
+ Agent personas (author/planner/healer): `npx waygraph agent-dive --loop claude`.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: waygraph-pilot
3
- description: Drive an existing waygraph Block graph as a real agent - use when a task needs to operate a web app that already has waygraph Blocks written for it (login, checkout, matching, chat, admin flows, etc.), not when writing new Blocks from scratch.
3
+ description: Drive an existing waygraph Block graph as a real agent - use when a task needs to operate a web app that already has waygraph Blocks written for it (login, checkout, matching, chat, admin flows, etc.), not when writing new Blocks from scratch. Includes how to paint demo-parity fixture highlights in Pilot via `auto highlight` (pilot:watch / --non-headless).
4
4
  ---
5
5
 
6
6
  Waygraph Pilot is not a planner you call and get an answer from - `pilot start` only
@@ -23,15 +23,42 @@ waygraph auto highlight <sessionId> '<json>' # paint rings/todos on the live pa
23
23
  just what's reachable from here - use it to plan several steps ahead before you start
24
24
  sending picks.
25
25
 
26
- ## Highlight fixtures (agent-sent narration)
26
+ ## Highlight fixtures (Pilot supports them — use `auto highlight`)
27
27
 
28
- Block `stubBefore` / `withHighlightFixtures` only paint in `waygraph demo`. In Pilot they
29
- land in `auto trace` as metadata but do **not** draw on the page. When a human is watching
30
- a headful session (or you want to narrate intent before a send), paint yourself with the
31
- same fixture surface:
28
+ **Yes, Pilot paints rings/todos/zoom/device on the live page.** That is what
29
+ `waygraph auto highlight` is for. It works on headful `pilot start --non-headless`
30
+ (consumer `pilot:watch`) and on headless sessions alike. Same fixture surface as
31
+ `waygraph demo` (rings, todos, focus veil, zoom badge, device viewport) — proven in
32
+ `tests/cli/auto-session.spec.ts` ("auto highlight: paints agent fixture rings…").
33
+
34
+ **Do not claim Pilot "doesn't support fixture highlights."** That is wrong. The only
35
+ thing that differs from demo is *who* triggers the paint:
36
+
37
+ | Mode | Who paints | How |
38
+ |------|------------|-----|
39
+ | `waygraph demo` | Engine, automatically | Block `stubBefore` / `stubAfter` / `withHighlightFixtures` run each step |
40
+ | Pilot / `auto --detach` | **You (the agent)** | `waygraph auto highlight <sessionId> '<json>'` before (or between) sends |
41
+
42
+ Block-authored `stubBefore` / `withHighlightFixtures` still exist on Blocks in Pilot —
43
+ they show up in `auto trace` as metadata — but they do **not** auto-draw. You re-express
44
+ the same intent with `auto highlight` (copy selectors/labels from the Block stubs or from
45
+ `auto dom`). Paint, then `auto send` the real Block. Clear when done.
32
46
 
33
47
  ```
48
+ # Headful watch session (rings visible to a human audience):
49
+ waygraph pilot start --non-headless
50
+ # → note sessionId from the bootstrap JSON
51
+
34
52
  waygraph auto highlight <sessionId> '{"rings":[{"selector":"#user-name","label":"Username","tone":"planned","focus":true},{"selector":"#password","label":"Password","tone":"info","detail":"secret"}],"todos":["Fill username","Fill password","Submit"],"todoIndex":0,"zoom":1.5,"holdMs":0}'
53
+ waygraph auto send <sessionId> fill-username
54
+ waygraph auto highlight <sessionId> '{"rings":[{"selector":"#password","label":"Password","tone":"planned","focus":true}],"todoIndex":1,"holdMs":0}'
55
+ waygraph auto send <sessionId> fill-password
56
+ waygraph auto highlight <sessionId> '{"clear":true}'
57
+ ```
58
+
59
+ More shapes:
60
+
61
+ ```
35
62
  waygraph auto highlight <sessionId> '{"device":"mobile","rings":[{"selector":".inventory_item:last-child","label":"Last item","zoom":1.6,"focus":true}],"holdMs":30000}'
36
63
  waygraph auto highlight <sessionId> '{"clear":true}'
37
64
  ```
@@ -1,8 +0,0 @@
1
- {
2
- "sessionId": "03710cfc",
3
- "socketPath": "/tmp/waygraph-auto/03710cfc.sock",
4
- "pid": 255515,
5
- "projectDir": "/home/dan/Desktop/Work/zsign/services/waygraph/examples/saucedemo",
6
- "startedAt": "2026-09-21T09:37:58.750Z",
7
- "headless": false
8
- }
@@ -1,8 +0,0 @@
1
- {
2
- "sessionId": "605d965b",
3
- "socketPath": "/tmp/waygraph-auto/605d965b.sock",
4
- "pid": 247729,
5
- "projectDir": "/home/dan/Desktop/Work/zsign/services/waygraph/examples/saucedemo",
6
- "startedAt": "2026-09-21T09:34:04.318Z",
7
- "headless": false
8
- }
@@ -1,8 +0,0 @@
1
- {
2
- "sessionId": "6b667734",
3
- "socketPath": "/tmp/waygraph-auto/6b667734.sock",
4
- "pid": 245167,
5
- "projectDir": "/home/dan/Desktop/Work/zsign/services/waygraph/examples/saucedemo",
6
- "startedAt": "2026-09-21T09:33:13.876Z",
7
- "headless": false
8
- }