@petukhovart/agent-view 0.3.0 → 0.6.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 (79) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/README.md +292 -143
  4. package/agents/design-conformance-runner.md +101 -0
  5. package/agents/verify-runner.md +97 -0
  6. package/dist/cdp/ax-cache.d.ts +7 -0
  7. package/dist/cdp/ax-cache.d.ts.map +1 -1
  8. package/dist/cdp/ax-cache.js +7 -0
  9. package/dist/cdp/ax-cache.js.map +1 -1
  10. package/dist/cdp/transport.d.ts.map +1 -1
  11. package/dist/cdp/transport.js +98 -27
  12. package/dist/cdp/transport.js.map +1 -1
  13. package/dist/cdp/types.d.ts +45 -2
  14. package/dist/cdp/types.d.ts.map +1 -1
  15. package/dist/cdp/types.js +6 -0
  16. package/dist/cdp/types.js.map +1 -1
  17. package/dist/cli/commands/console.d.ts +1 -0
  18. package/dist/cli/commands/console.d.ts.map +1 -1
  19. package/dist/cli/commands/console.js +1 -0
  20. package/dist/cli/commands/console.js.map +1 -1
  21. package/dist/cli/commands/dom.d.ts +4 -0
  22. package/dist/cli/commands/dom.d.ts.map +1 -1
  23. package/dist/cli/commands/dom.js +4 -0
  24. package/dist/cli/commands/dom.js.map +1 -1
  25. package/dist/cli/commands/drag.d.ts +13 -0
  26. package/dist/cli/commands/drag.d.ts.map +1 -0
  27. package/dist/cli/commands/drag.js +72 -0
  28. package/dist/cli/commands/drag.js.map +1 -0
  29. package/dist/cli/commands/scene.d.ts +1 -0
  30. package/dist/cli/commands/scene.d.ts.map +1 -1
  31. package/dist/cli/commands/scene.js +2 -0
  32. package/dist/cli/commands/scene.js.map +1 -1
  33. package/dist/cli/commands/screenshot.d.ts +1 -0
  34. package/dist/cli/commands/screenshot.d.ts.map +1 -1
  35. package/dist/cli/commands/screenshot.js +4 -0
  36. package/dist/cli/commands/screenshot.js.map +1 -1
  37. package/dist/cli/commands/snap.d.ts +1 -0
  38. package/dist/cli/commands/snap.d.ts.map +1 -1
  39. package/dist/cli/commands/snap.js +2 -0
  40. package/dist/cli/commands/snap.js.map +1 -1
  41. package/dist/cli/commands/watch.d.ts +12 -0
  42. package/dist/cli/commands/watch.d.ts.map +1 -0
  43. package/dist/cli/commands/watch.js +233 -0
  44. package/dist/cli/commands/watch.js.map +1 -0
  45. package/dist/cli/index.js +48 -1
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/config/manager.js +1 -1
  48. package/dist/config/types.d.ts +0 -3
  49. package/dist/config/types.d.ts.map +1 -1
  50. package/dist/inspectors/dom/index.d.ts +13 -0
  51. package/dist/inspectors/dom/index.d.ts.map +1 -1
  52. package/dist/inspectors/dom/index.js +255 -103
  53. package/dist/inspectors/dom/index.js.map +1 -1
  54. package/dist/inspectors/scene/formatter.d.ts.map +1 -1
  55. package/dist/inspectors/scene/formatter.js +56 -8
  56. package/dist/inspectors/scene/formatter.js.map +1 -1
  57. package/dist/inspectors/scene/types.d.ts +1 -0
  58. package/dist/inspectors/scene/types.d.ts.map +1 -1
  59. package/dist/inspectors/watch/index.d.ts +18 -0
  60. package/dist/inspectors/watch/index.d.ts.map +1 -0
  61. package/dist/inspectors/watch/index.js +39 -0
  62. package/dist/inspectors/watch/index.js.map +1 -0
  63. package/dist/inspectors/watch/types.d.ts +70 -0
  64. package/dist/inspectors/watch/types.d.ts.map +1 -0
  65. package/dist/inspectors/watch/types.js +21 -0
  66. package/dist/inspectors/watch/types.js.map +1 -0
  67. package/dist/server/server.d.ts +9 -1
  68. package/dist/server/server.d.ts.map +1 -1
  69. package/dist/server/server.js +279 -48
  70. package/dist/server/server.js.map +1 -1
  71. package/dist/server/watch-session.d.ts +32 -0
  72. package/dist/server/watch-session.d.ts.map +1 -0
  73. package/dist/server/watch-session.js +165 -0
  74. package/dist/server/watch-session.js.map +1 -0
  75. package/dist/types.d.ts +2 -0
  76. package/dist/types.d.ts.map +1 -1
  77. package/package.json +62 -60
  78. package/skills/verify/SKILL.md +84 -13
  79. package/skills/verify-recipe/SKILL.md +202 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: verify
3
- description: "Visual + runtime verification of desktop apps via Chrome DevTools Protocol. Use when modifying UI components, fixing visual bugs, testing user interactions, verifying layout, or when any workflow phase needs to inspect the running application — DOM, screenshots, scene graph, runtime state in pages and SharedWorkers/ServiceWorkers, or console errors. Triggers on: verify, check UI, test how it looks, visual regression, screenshot, inspect DOM, check store/state, read worker, console errors, runtime check, eval in page."
4
- allowed-tools: Bash(agent-view *), Bash(rtk agent-view *)
3
+ description: "Visual + runtime verification of desktop apps via Chrome DevTools Protocol. Use when modifying UI components, fixing visual bugs, testing user interactions, verifying layout, or when any workflow phase needs to inspect the running application — DOM, screenshots, scene graph, runtime state in pages and SharedWorkers/ServiceWorkers, console errors, or reactive-state diffs over time. Triggers on: verify, check UI, test how it looks, visual regression, screenshot, inspect DOM, check store/state, watch state changes, what changed after click, wait until state, read worker, console errors, runtime check, eval in page."
4
+ allowed-tools: Bash(agent-view *)
5
5
  ---
6
6
 
7
7
  # Visual Verification with agent-view
@@ -12,7 +12,7 @@ You have access to `agent-view` CLI for inspecting and interacting with desktop
12
12
 
13
13
  The target project must have:
14
14
  1. `agent-view.config.json` in project root (run `agent-view init` to generate)
15
- 2. CDP enabled in the app (e.g. `--remote-debugging-port=9222` for Electron)
15
+ 2. CDP enabled in the app (e.g. `--remote-debugging-port=9876` for Electron — avoid `9222`, it's Chrome's own default and collides when Chrome is open)
16
16
 
17
17
  If config is missing, run `agent-view init` first.
18
18
 
@@ -27,26 +27,46 @@ agent-view stop # Stop the lazy server
27
27
 
28
28
  ### DOM Inspection
29
29
  ```bash
30
- rtk agent-view dom # DOM accessibility tree (default window)
31
- rtk agent-view dom --window <id|name> # Specific window
32
- rtk agent-view dom --filter "button" # Filter by text/role
33
- rtk agent-view dom --depth 3 # Limit tree depth
30
+ agent-view dom # DOM accessibility tree (default window)
31
+ agent-view dom --window <id|name> # Specific window
32
+ agent-view dom --filter "button" # Filter by text/role
33
+ agent-view dom --depth 3 # Limit tree depth
34
+ agent-view dom --compact # Merge single-child chains onto one line (~40-60% fewer tokens)
35
+ agent-view dom --count # Count of all visible nodes (single integer line)
36
+ agent-view dom --filter "row" --count # Count matching nodes — e.g. "does this table have 5 rows?"
37
+ agent-view dom --max-lines 200 # Hard line budget; refs for truncated nodes still stored
38
+ agent-view dom --diff # Lines changed since last dom call (+ added / - removed)
34
39
  ```
35
40
 
41
+ `--count` skips tree output and ref mutations — cheapest way to assert "element exists N times" without loading the full tree into context.
42
+
36
43
  ### Interaction
37
44
  ```bash
38
45
  agent-view click <ref> # Click element by ref from dom output
39
46
  agent-view click --pos 100,200 # Click by coordinates (for canvas)
40
47
  agent-view fill <ref> "text" # Type into input field
48
+ agent-view drag --from <ref> --to <ref> # Drag element to another element by ref
49
+ agent-view drag --from-pos 50,80 --to-pos 200,300 # Drag by coordinates (for canvas / Pixi)
50
+ agent-view drag --from <ref> --to <ref> --steps 25 --hold-ms 60 # Smoother movement, longer hold
41
51
  ```
42
52
 
53
+ `drag` dispatches `mousePressed` → N × `mouseMoved` → `mouseReleased` via CDP. Endpoints can mix
54
+ ref and coordinate (e.g. `--from <ref> --to-pos 400,300`). For canvas/Pixi targets always use
55
+ `--from-pos`/`--to-pos` — derive the centroid via `agent-view eval` from the scene graph.
56
+ Refs are resolved fresh on each call, so window resizes between snapshots are tolerated.
57
+ Increase `--steps` for handlers using `globalpointermove` so intermediate frames are not skipped.
58
+
43
59
  ### Screenshots
44
60
  ```bash
45
61
  agent-view screenshot --scale 0.5 # Recommended: JPEG at half-res (~3× fewer vision tokens)
46
62
  agent-view screenshot --scale 0.5 --window <id> # Specific window
63
+ agent-view screenshot --crop "Sidebar" # Crop to element bounding box (~1.6k tokens — 12× win)
64
+ agent-view screenshot --crop "Chart" --scale 0.5 # Crop + scale (stacks)
47
65
  agent-view screenshot # Full-res PNG (expensive: ~19k tokens at 1920×1080)
48
66
  ```
49
67
 
68
+ `--crop <filter>` resolves the element with the same filter syntax as `dom --filter`, then crops the screenshot to its bounding box. Prefer `--crop` over full-window screenshots whenever you only need to inspect a specific section. Falls back to full-window with a stderr warning if the filter matches nothing.
69
+
50
70
  ### Runtime State (`eval`)
51
71
 
52
72
  Reads runtime values DOM/screenshot can't reveal — store contents, computed flags, worker internals.
@@ -65,6 +85,24 @@ When to reach for `eval` instead of `dom`:
65
85
  - The target is a worker (`shared_worker`, `service_worker`, `worker`) — DOM doesn't exist there.
66
86
  - You need a precise number/string answer, not a tree to scan.
67
87
 
88
+ ### Reactive State (`watch`)
89
+
90
+ Streams JSON-patch diffs of an expression over time. Use when you need to see *what changed* between an action and a final state — `eval` shows the snapshot, `watch` shows the trajectory. **Requires `"allowEval": true`.**
91
+
92
+ ```bash
93
+ agent-view watch "store.cart.total" # 250ms poll, default 10 changes or 30s
94
+ agent-view watch "appState" --until "appState.status === 'ready'" # wait-for-condition with diff log
95
+ agent-view watch "store.user" --max-changes 1 # capture exactly one change after a click
96
+ agent-view watch "appState" --json # NDJSON, machine-readable
97
+ ```
98
+
99
+ When to reach for `watch` instead of `eval`:
100
+ - Debugging "the click did X but state shows Y — what happened in between?"
101
+ - Time-based assertions ("wait until store.status === 'ready'") — `--until` exits cleanly when truthy.
102
+ - Confirming an action triggered the *expected* sequence of mutations, not just the final state.
103
+
104
+ Output: `init` line (baseline), one line per RFC 6902 op (`replace /path old → new`, `add /items/0 ...`), final `stop` line with reason. Snapshot size cap 256 KB — narrow the expression (`store.x.y`, not `store`) for large objects.
105
+
68
106
  ### Console (`console`)
69
107
 
70
108
  Streams `Runtime.consoleAPICalled` + `Log.entryAdded`. Use to confirm a flow finished without errors, or to surface a specific warning after an interaction.
@@ -72,12 +110,17 @@ Streams `Runtime.consoleAPICalled` + `Log.entryAdded`. Use to confirm a flow fin
72
110
  ```bash
73
111
  agent-view console # buffered messages from auto-attached targets
74
112
  agent-view console --level error,warn # filter
75
- agent-view console --target sync-worker # one target
113
+ agent-view console --target sync-worker # one target (title/URL substring, same fuzzy semantics as eval --target)
114
+ agent-view console --target IJ56KL # one target (exact id)
76
115
  agent-view console --follow --timeout 10 # stream window (use sparingly — 10s of waiting)
116
+ agent-view console --follow --until "ready" # exit as soon as a message contains "ready"
117
+ agent-view console --follow --until "/error/i" # exit on regex match (case-insensitive)
77
118
  agent-view console --clear # baseline before an interaction
78
119
  agent-view console --since "2026-04-26T10:00:00Z"
79
120
  ```
80
121
 
122
+ `--until` requires `--follow`. Exits immediately when a message matches (substring or `/regex/flags`). On timeout without match exits non-zero.
123
+
81
124
  Standard pattern for "did this action error?":
82
125
  ```bash
83
126
  agent-view console --clear
@@ -109,7 +152,9 @@ agent-view scene # Scene graph from configured engine
109
152
  agent-view scene --filter "player" # Filter by object name/type
110
153
  agent-view scene --verbose # Extended props (scale, alpha, rotation)
111
154
  agent-view scene --diff # Changes since last call
155
+ agent-view scene --compact # Merge single-child chains onto one line (reduces output)
112
156
  agent-view snap # DOM + Scene combined
157
+ agent-view snap --scale 0.5 # DOM + Scene + Screenshot (path appended as === Screenshot === section)
113
158
  ```
114
159
 
115
160
  ## Picking the right tool
@@ -119,24 +164,48 @@ Verifications cost very different amounts. Pick the cheapest tool that can actua
119
164
  | The question is about… | Use | Why |
120
165
  |---|---|---|
121
166
  | Element existence / text / role | `dom --filter` | Cheapest, structured, no vision tokens |
167
+ | Count of matching elements | `dom --filter X --count` | Single integer, no tree output, no ref mutations |
122
168
  | App state, store contents, computed values | `eval "expr"` | DOM doesn't expose JS state; reading the tree to infer it is wasteful and unreliable |
169
+ | State *trajectory* — what changed during/after an action | `watch "expr" --until …` or `--max-changes 1` | `eval` shows the final snapshot only; `watch` shows the diffs in order |
123
170
  | Worker logic (SharedWorker / ServiceWorker) | `eval --target <name>` | Workers have no DOM at all |
124
171
  | Did the last action throw or warn? | `console --clear` before, `console --level error,warn` after | Catches errors that don't surface in the DOM |
125
- | Layout, spacing, visual regression | `screenshot --scale 0.5` | The only tool that sees pixels but expensive (~6k tokens), use last |
172
+ | Layout/visual of a specific element | `screenshot --crop "<element>"` | ~1.6k tokens (1 tile)crops to bounding box, massive token win |
173
+ | Layout, spacing, full-window visual regression | `screenshot --scale 0.5` | The only tool that sees pixels — but expensive (~6k tokens), use last |
126
174
  | Canvas/WebGL scene contents | `scene --diff` | DOM is empty for canvas apps |
175
+ | What DOM nodes changed after an interaction | `dom --diff` | Returns only `+`/`-` lines; much cheaper than re-reading the full tree |
127
176
 
128
177
  When two tools could answer the same question, prefer the one higher up the table. A common mistake is screenshotting to check "is the count = 5?" when `eval "store.counter"` returns the number directly for ~50 tokens.
129
178
 
130
179
  ## Verification Workflow
131
180
 
181
+ ### Recipe Execution Mode (preferred when a recipe exists)
182
+
183
+ If the developer points you at a `.claude/verify-recipes/<slug>.md` file, OR you discover one matching the current task via `ls .claude/verify-recipes/`, **delegate execution to the `verify-runner` subagent** instead of running commands yourself.
184
+
185
+ Why: recipe execution is mechanical (run commands, compare to `Expected:`, report). It does not need Opus-level reasoning, but the raw output (DOM dumps, screenshots, eval results) easily exceeds 30k tokens of context noise. Delegating to a Haiku subagent keeps your context clean and cuts cost ~10×.
186
+
187
+ How to delegate:
188
+
189
+ 1. Resolve the window id once: `agent-view discover` → pick the main window's id.
190
+ 2. Spawn `verify-runner` via the Agent tool with a prompt containing:
191
+ - Absolute `recipe_path`
192
+ - Resolved `window_id`
193
+ - Any extra context (e.g. "user is already logged in", "GIS widget already mounted")
194
+ 3. Wait for the JSON report. Read `summary`, `blocking_issues`, and any `failed` step diagnoses.
195
+ 4. **If `design_conformance_section: true`** in the report: also spawn `design-conformance-runner` in parallel, passing the `design_conformance_pairs` array. Merge both reports before answering the user.
196
+ 5. For `requires_visual_review` steps that have no design ref attached: open the screenshot yourself with `Read` and decide pass/fail.
197
+ 6. For `failed` steps: re-run the specific failing command yourself if you need richer evidence to diagnose. Do not re-execute the whole recipe.
198
+
199
+ Output to the user: a tight summary — what passed, what failed, what needs visual review, and (if any) which design conformance issues to fix. Do not paste the raw JSON unless asked.
200
+
132
201
  ### Ad-hoc Mode (standalone)
133
202
 
134
203
  After making code changes:
135
204
 
136
205
  1. **Determine affected areas** from git diff
137
206
  2. **Ensure app is running**: `agent-view launch` or `agent-view discover`
138
- 3. **Inspect DOM**: `rtk agent-view dom --filter "<area>" --depth 2` — check structure matches expectations
139
- 4. **Interact if needed**: `agent-view click`/`fill` → `rtk agent-view dom --filter` to verify state changed
207
+ 3. **Inspect DOM**: `agent-view dom --filter "<area>" --depth 2` — check structure matches expectations
208
+ 4. **Interact if needed**: `agent-view click`/`fill` → `agent-view dom --filter` to verify state changed
140
209
  5. **For canvas apps**: `agent-view scene --diff` to see what changed
141
210
  6. **For non-DOM truth** (store, computed values, worker state): `agent-view eval` — much cheaper than reading the DOM tree to infer state
142
211
  7. **After any interaction that could fail silently**: `agent-view console --level error` — catches uncaught exceptions, network failures, framework warnings
@@ -176,9 +245,11 @@ Vision tokens dominate cost. One full-res screenshot ≈ 19k tokens (1920×1080,
176
245
  | Technique | Savings |
177
246
  |---|---|
178
247
  | `agent-view eval "expr"` for state checks | Returns one value (~50 tokens) instead of a DOM/screenshot |
179
- | `rtk agent-view dom --filter X --depth 2` | Compresses text output via RTK |
248
+ | `agent-view dom --filter "row" --count` | Single integer answer zero tree tokens |
249
+ | `agent-view dom --filter X --depth 2` | Narrow tree to relevant subtree, cap depth |
180
250
  | `agent-view screenshot --scale 0.5` | ~3× fewer vision tokens (4 tiles) |
181
251
  | `agent-view screenshot --scale 0.25` | ~12× fewer vision tokens (1 tile, ~1.6k tokens) |
252
+ | `agent-view screenshot --crop "<element>"` | ~12× fewer in best case (1 tile) — crops to element bounding box |
182
253
  | DOM/eval-first: screenshot only for final visual confirm | Eliminates most screenshot calls |
183
254
 
184
- **Default rule**: if the answer is a value → `eval`; if the answer is "is element X visible/correct?" → `rtk agent-view dom --filter`; only call `screenshot --scale 0.5` for final visual proof or layout bugs that pixels alone can show.
255
+ **Default rule**: if the answer is a value → `eval`; if the answer is "is element X visible/correct?" → `agent-view dom --filter`; if you need pixels for a specific section → `screenshot --crop "<element>"` (one tile); only call `screenshot --scale 0.5` for full-window visual proof.
@@ -0,0 +1,202 @@
1
+ ---
2
+ name: verify-recipe
3
+ description: "Generates a concrete, command-by-command agent-view recipe for verifying a feature or bugfix. Use when the developer wants to write a verify-recipe.md, create a verification plan, build an agent-view recipe, or produce a verify checklist for a change they shipped. Triggers on: write a verify-recipe, write verification steps, generate verify steps for the feature/bug I just shipped/fixed, make a verify-recipe.md, what should I run to verify X, create a verification plan, agent-view recipe for this fix, verify checklist for this feature. Does NOT execute the checks — it authors the plan. For running checks against a live app, use the verify skill instead."
4
+ allowed-tools: Read, Write, Bash(agent-view *)
5
+ ---
6
+
7
+ # Verification Recipe Generator
8
+
9
+ You help the developer author a disciplined, cheapest-first verification recipe for a feature they shipped or a bug they fixed. You do not run the checks — you produce a `.claude/verify-recipes/<slug>.md` file that any AI coding agent can execute later.
10
+
11
+ ## What this produces
12
+
13
+ A file at `.claude/verify-recipes/<kebab-slug>.md` containing:
14
+
15
+ - **REPRO STEPS** — exact state the app must be in before checks run
16
+ - **NARROWED SIGNAL** — the measurable indicator that proves success or failure
17
+ - **EVIDENCE COMMANDS** — ordered `agent-view` calls, cheapest first, each annotated with what it proves
18
+ - **POSITIVE-CASE ASSERTIONS** — what "pass" looks like for each command
19
+ - **REGRESSION CHECKS** — adjacent paths that must not have broken
20
+
21
+ Create the directory if missing: `mkdir -p .claude/verify-recipes`
22
+
23
+ ## Methodology
24
+
25
+ Frame the recipe with **hard-debug** discipline. That skill defines the chain: REPRO → narrowed signal → minimize scope → root-cause check → fix verification. Apply the same logic here in authoring mode:
26
+
27
+ 1. Start from a reproducible starting state, not "open the app and poke around"
28
+ 2. Convert vague expectations ("looks right") into measurable signals ("store.user.role === 'admin'")
29
+ 3. Prefer the cheapest tool that can answer the question — a value check costs ~50 tokens, a screenshot costs ~6 000
30
+ 4. Include at least one negative-case check (the old symptom must no longer appear)
31
+ 5. Include at least one regression check (an adjacent flow must still work)
32
+
33
+ ## Tool-cost decision tree
34
+
35
+ Pick the first row that can answer the question. Only go lower when the row above can't:
36
+
37
+ | Question | Command | Why it's cheapest |
38
+ |---|---|---|
39
+ | Element exists / has specific text / role | `agent-view dom --filter "<text>" --depth 2` | Structured text, zero vision tokens |
40
+ | App state, store value, computed flag | `agent-view eval "<expr>"` | Returns the value directly; DOM inference is wasteful and fragile |
41
+ | What changed between action and final state | `agent-view watch "<expr>" --until "<condition>"` or `--max-changes 1` | `eval` shows the snapshot; `watch` shows the trajectory |
42
+ | SharedWorker / ServiceWorker internal state | `agent-view eval --target <name> "<expr>"` | Workers have no DOM; this is the only path |
43
+ | Did this action throw or warn silently? | `agent-view console --clear` before, `agent-view console --level error,warn` after | Catches uncaught exceptions and network failures invisible to DOM |
44
+ | Layout, spacing, visual regression | `agent-view screenshot --scale 0.5` | Last resort — the only tool that sees pixels, but costs ~6 000 tokens |
45
+ | Canvas / WebGL scene state | `agent-view scene --diff` | DOM is empty for canvas apps |
46
+
47
+ **Anti-patterns to reject:**
48
+ - Opening with a screenshot to "see the state" — use `dom --filter` or `eval` first
49
+ - Using `eval` when `dom --filter` answers the question
50
+ - Assertions that depend on transient state without `watch --until` to stabilize first
51
+ - "Check that it looks right" — every assertion must be a concrete pass/fail criterion. The single legitimate exception is the `## Design Conformance` section, which delegates visual judgment to the design-conformance-runner subagent against an explicit reference image.
52
+ - Inventing design reference paths (`.figma-refs/...`, `assets/mockups/...`) when the developer did not provide them. No refs → no Design Conformance section.
53
+
54
+ ## Workflow
55
+
56
+ ### Step 1 — gather context
57
+
58
+ When invoked, ask the developer in plain text (no tool calls yet):
59
+
60
+ 1. What was shipped or fixed? (feature name or bug description)
61
+ 2. What was the original symptom or expected behavior?
62
+ 3. Any known failure mode or edge case to cover?
63
+ 4. (Optional) Are there design reference images to verify against? If yes — local path, glob, or list of files. **Only local files are supported.**
64
+
65
+ Wait for the response before continuing.
66
+
67
+ If the user provides design refs in step 4, store them for Step 2's optional `Design Conformance` section. If not provided, skip that section entirely — never invent a path or assume a convention.
68
+
69
+ ### Step 2 — draft the recipe
70
+
71
+ Use the answers to produce a recipe with these sections:
72
+
73
+ ```markdown
74
+ # Verify: <feature or fix name>
75
+
76
+ Generated: <date>
77
+ Scope: <one sentence describing what this covers>
78
+
79
+ ## Repro Steps
80
+ 1. <Exact starting state — window open, user logged in, specific route, etc.>
81
+ 2. <Action(s) that trigger the behavior under test>
82
+
83
+ ## Narrowed Signal
84
+ <!-- The one measurable thing that proves it works -->
85
+ `<agent-view command>` must return `<expected value>`.
86
+
87
+ ## Evidence Commands
88
+
89
+ ### 1. <What this proves>
90
+ ```bash
91
+ agent-view <command>
92
+ ```
93
+ Expected: <concrete criterion — value, text, absence of error>
94
+ Cost: ~<N> tokens
95
+
96
+ ### 2. ...
97
+
98
+ ## Positive-Case Assertions
99
+ - [ ] <criterion>
100
+ - [ ] <criterion>
101
+
102
+ ## Regression Checks
103
+ - [ ] <adjacent flow> — `agent-view <command>` → `<expected>`
104
+
105
+ ## Design Conformance
106
+ <!-- INCLUDE THIS SECTION ONLY IF the developer provided design refs in Step 1 question 4. -->
107
+ <!-- Each pair: a screenshot command + an absolute path to the expected reference image. -->
108
+ <!-- The design-conformance-runner subagent reads this section, runs the screenshot commands, and visually compares against the expected refs. -->
109
+ <!-- Do NOT invent design ref paths. Do NOT assume a convention (e.g. .figma-refs/). Use exactly what the developer provided. -->
110
+
111
+ | Step Label | Screenshot Command | Expected Reference |
112
+ |---|---|---|
113
+ | <area name e.g. "filter panel"> | `agent-view screenshot --crop "<area>" --scale 0.5` | `<absolute path to expected PNG/JPEG>` |
114
+ | <area name> | `agent-view screenshot --window $W --scale 0.5` | `<absolute path>` |
115
+
116
+ Tolerance: `normal` (default — flag deviations a designer would notice in code review). Use `loose` only if the developer says exact pixel parity is not required.
117
+
118
+ ## Anti-patterns avoided
119
+ - <note any recipe-specific traps, e.g. "state resets on reload — watch needed before dom check">
120
+ ```
121
+
122
+ ### Step 3 — save the file
123
+
124
+ Determine a kebab-slug from the feature/fix name (e.g. `login-redirect-fix`, `cart-total-display`).
125
+
126
+ Save to `.claude/verify-recipes/<slug>.md`. Create the directory first if it doesn't exist.
127
+
128
+ Confirm the path to the developer.
129
+
130
+ ## Worked example: "fixed login redirect bug"
131
+
132
+ **Developer input:**
133
+ > Fixed a bug where after login, the redirect went to `/home` instead of `/dashboard`. Store mutation `SET_REDIRECT_PATH` was missing. No visual change — purely a routing issue.
134
+
135
+ **Recipe produced:**
136
+
137
+ ```markdown
138
+ # Verify: Login Redirect Fix
139
+
140
+ Generated: 2026-04-27
141
+ Scope: Confirms that a successful login routes to /dashboard, not /home, and that the store mutation fires correctly.
142
+
143
+ ## Repro Steps
144
+ 1. App running, user logged out, at `/login`
145
+ 2. Fill email + password, click "Sign in"
146
+
147
+ ## Narrowed Signal
148
+ `agent-view eval "router.currentRoute.path"` must return `"/dashboard"`.
149
+
150
+ ## Evidence Commands
151
+
152
+ ### 0. Setup — baseline console (before any action)
153
+ ```bash
154
+ agent-view console --clear
155
+ ```
156
+
157
+ ### 1. Confirm redirect target
158
+ ```bash
159
+ agent-view fill <email-ref> "admin@example.com"
160
+ agent-view fill <password-ref> "password"
161
+ agent-view click <signin-ref>
162
+ agent-view watch "router.currentRoute.path" --until "router.currentRoute.path === '/dashboard'"
163
+ ```
164
+ Expected: `replace / "/login" → "/dashboard"` in watch output
165
+ Cost: ~100 tokens
166
+
167
+ ### 2. Confirm mutation fired
168
+ ```bash
169
+ agent-view eval "store.state.auth.redirectPath"
170
+ ```
171
+ Expected: `"/dashboard"` (not `"/home"`, not `null`)
172
+ Cost: ~50 tokens
173
+
174
+ ### 3. No errors during login flow
175
+ ```bash
176
+ agent-view console --level error,warn
177
+ ```
178
+ Expected: `(no console messages)`
179
+ Cost: ~30 tokens
180
+
181
+ ### 4. Regression — logout returns to /login
182
+ ```bash
183
+ agent-view click <logout-ref>
184
+ agent-view eval "router.currentRoute.path"
185
+ ```
186
+ Expected: `"/login"`
187
+ Cost: ~60 tokens
188
+
189
+ ## Positive-Case Assertions
190
+ - [ ] `router.currentRoute.path` === `/dashboard` after login
191
+ - [ ] `store.state.auth.redirectPath` === `/dashboard`
192
+ - [ ] No console errors during the flow
193
+
194
+ ## Regression Checks
195
+ - [ ] Logout → `/login` still works
196
+
197
+ ## Anti-patterns avoided
198
+ - Not using screenshot to confirm route (route is a string — eval is 120× cheaper)
199
+ - watch used before eval so route change is confirmed to have settled, not just sampled mid-transition
200
+ ```
201
+
202
+ **Saved to:** `.claude/verify-recipes/login-redirect-fix.md`