start-vibing 4.2.0 → 4.3.1

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.
@@ -0,0 +1,258 @@
1
+ # Component, Modal & Flow Discovery Playbook
2
+
3
+ > How sd-audit systematically exercises EVERY interactive element before
4
+ > running heuristics. Without this, the audit only sees static page snaps
5
+ > and misses modal contents, flow state, hover/focus/active variants, and
6
+ > loading/empty/error states.
7
+ >
8
+ > This playbook runs as **Step 2.5** in sd-audit, after route discovery
9
+ > and before per-viewport heuristic passes.
10
+
11
+ ## Why this matters
12
+
13
+ Static screenshots of pages show ~30% of what users interact with. The other 70%
14
+ lives inside modals, drawers, dropdowns, command palettes, error flows, empty
15
+ states, loading states, hover menus, focus rings. A page can score 95/100 on
16
+ Lighthouse and be unusable because its "Create" modal is broken — and the
17
+ auditor never opened it.
18
+
19
+ ## Discovery phases
20
+
21
+ ### Phase A — Interactive inventory (per page × viewport)
22
+
23
+ After navigating and dismissing banners:
24
+
25
+ ```js
26
+ // browser_evaluate
27
+ (() => {
28
+ const roots = [
29
+ '[role="button"]',
30
+ 'button',
31
+ 'a[href]',
32
+ '[role="link"]',
33
+ '[role="menuitem"]',
34
+ '[role="tab"]',
35
+ '[role="switch"]',
36
+ '[role="checkbox"]',
37
+ '[role="radio"]',
38
+ '[aria-haspopup]',
39
+ '[aria-expanded]',
40
+ '[data-trigger]',
41
+ '[data-state]',
42
+ 'input',
43
+ 'select',
44
+ 'textarea',
45
+ 'summary',
46
+ ];
47
+ const items = [];
48
+ roots.forEach(sel => {
49
+ document.querySelectorAll(sel).forEach(el => {
50
+ if (!el.offsetParent && getComputedStyle(el).position !== 'fixed') return;
51
+ const r = el.getBoundingClientRect();
52
+ if (r.width === 0 || r.height === 0) return;
53
+ items.push({
54
+ selector: sel,
55
+ tag: el.tagName,
56
+ role: el.getAttribute('role'),
57
+ name: el.getAttribute('aria-label') || el.textContent?.trim().slice(0, 60) || '',
58
+ type: el.getAttribute('type'),
59
+ haspopup: el.getAttribute('aria-haspopup'),
60
+ expanded: el.getAttribute('aria-expanded'),
61
+ disabled: el.disabled || el.getAttribute('aria-disabled') === 'true',
62
+ rect: { x: r.x, y: r.y, w: r.width, h: r.height },
63
+ });
64
+ });
65
+ });
66
+ return items;
67
+ })()
68
+ ```
69
+
70
+ Save to `.super-design/sessions/<id>/interactive/<slug>_<vp>.json`.
71
+
72
+ Classify each:
73
+ - **navigation** — links, tabs, back buttons
74
+ - **action** — primary CTAs, submit, delete, save
75
+ - **trigger** — opens modal/drawer/dropdown (`aria-haspopup`, `data-trigger`)
76
+ - **input** — form fields
77
+ - **state-toggle** — switches, checkboxes, expanders
78
+
79
+ ### Phase B — Modal & overlay discovery
80
+
81
+ For each trigger from Phase A:
82
+
83
+ ```
84
+ 1. Pre-click snapshot (already have from Phase 1)
85
+ 2. browser_click({ ref }) # click the trigger
86
+ 3. browser_wait_for(text="<expected modal content>") or 500ms
87
+ 4. browser_snapshot → save as snapshots/<slug>_<vp>_<triggerName>_open.yaml
88
+ 5. browser_take_screenshot fullPage + element-scoped → screens/components/
89
+ 6. browser_console_messages(level="error") → record
90
+ 7. Inside open modal, run Phase A again (nested inventory)
91
+ 8. Look for [role="dialog"] or [data-state="open"] to confirm it opened
92
+ 9. Exercise modal internals:
93
+ - Tab through to find focus trap
94
+ - Press Escape to confirm dismiss
95
+ - Resize to mobile — check if it becomes bottom-sheet
96
+ 10. Close modal (button or Escape)
97
+ 11. Re-snapshot → confirm background restored, focus returned to trigger
98
+ ```
99
+
100
+ **Modals a junior agent misses:**
101
+ - Confirmation dialogs (delete confirm, logout confirm)
102
+ - Date pickers (calendar popover)
103
+ - Color pickers
104
+ - Combobox dropdowns (autocomplete search)
105
+ - Popover menus (dropdown with options)
106
+ - Sheet / drawer (slide-in from right or bottom)
107
+ - Command palette (Cmd+K)
108
+ - Tooltips (hover-triggered on desktop)
109
+ - Toast notifications (programmatic — trigger an action that causes one)
110
+ - Error modals (submit invalid form)
111
+ - Share sheets
112
+ - File upload dialogs (click input[type=file])
113
+
114
+ ### Phase C — Flow exercising
115
+
116
+ A **flow** is a multi-step user journey. Every app has 3–10 critical flows.
117
+ sd-audit must auto-discover and exercise them.
118
+
119
+ **Auto-discover flows from routes + component names:**
120
+
121
+ | Route / name hint | Flow |
122
+ |---|---|
123
+ | `/login`, `/signin`, `/auth` | Login flow (happy + wrong password + locked account) |
124
+ | `/register`, `/signup` | Registration flow |
125
+ | `/forgot`, `/reset` | Password reset flow |
126
+ | `/onboarding`, `/welcome` | First-run flow |
127
+ | `/checkout`, `/cart` | Checkout flow (incl. errors: declined card, validation) |
128
+ | `/dashboard`, `/home` (authed) | Post-auth landing → primary CTA flow |
129
+ | List route (`/users`, `/orders`) | CRUD — create, edit, view, delete, filter, search, paginate |
130
+ | Detail route (`/users/:id`) | Edit flow, delete flow, related actions |
131
+ | `/settings`, `/profile` | Profile edit, preference toggles, account delete |
132
+ | `/support`, `/help`, `/chat` | Messaging flow |
133
+
134
+ **Per flow:**
135
+
136
+ ```
137
+ 1. Plan steps (list of expected screens + actions)
138
+ 2. Execute step-by-step:
139
+ - Navigate / click to advance
140
+ - Per step: snapshot + screenshot + console
141
+ - Test error path (invalid input, network error via DevTools)
142
+ - Test back button preserves state
143
+ 3. Capture final success state (confirmation page, toast, redirect)
144
+ 4. If flow depends on creating test data, use burner account
145
+ ```
146
+
147
+ Save per-flow artifacts under `.super-design/sessions/<id>/flows/<flow_name>/step_NN_<action>.png`.
148
+
149
+ ### Phase D — State matrix per component
150
+
151
+ For each UI component class (Button, Input, Card, ListRow, Modal, NavItem…),
152
+ capture:
153
+
154
+ | State | How to trigger |
155
+ |---|---|
156
+ | default | Initial render |
157
+ | hover | `browser_hover` (desktop only, gate `@media hover`) |
158
+ | focus | Tab to element via `browser_press_key(Tab)` until focused |
159
+ | focus-visible | Same as focus (most systems collapse them now) |
160
+ | active | `browser_press_key` Enter/Space while focused |
161
+ | disabled | Find a disabled example (e.g., form before valid) |
162
+ | loading | Submit form → catch transient state; OR throttle network via DevTools |
163
+ | error | Invalid input + submit |
164
+ | empty | Navigate to route with no data (burner account OR delete all) |
165
+ | success | Complete a flow successfully |
166
+ | selected | Click tab / radio / checkbox that shows selected variant |
167
+
168
+ Save per component class:
169
+ ```
170
+ .super-design/sessions/<id>/components/
171
+ Button/
172
+ default.png
173
+ hover.png
174
+ focus.png
175
+ active.png
176
+ disabled.png
177
+ loading.png
178
+ Input/...
179
+ Modal/...
180
+ ```
181
+
182
+ Output `.super-design/sessions/<id>/component-state-matrix.json`:
183
+
184
+ ```json
185
+ {
186
+ "Button": {
187
+ "states_captured": ["default", "hover", "focus", "active", "disabled", "loading"],
188
+ "states_missing": ["error"],
189
+ "evidence": { "default": "components/Button/default.png", "..." }
190
+ },
191
+ "...": {}
192
+ }
193
+ ```
194
+
195
+ **Missing states → finding.**
196
+
197
+ ### Phase E — Form state coverage
198
+
199
+ Per form discovered, test:
200
+ 1. Empty submit → validation messages
201
+ 2. Each field invalid individually → per-field error
202
+ 3. All valid → success state
203
+ 4. Server error (simulate 500) → error recovery
204
+ 5. Network offline → offline handling
205
+ 6. Paste into password field → paste NOT blocked
206
+ 7. Autocomplete tokens on login fields (`username`, `current-password`, `one-time-code`)
207
+ 8. Tab order matches visual order
208
+ 9. Submit via Enter key works
209
+ 10. Mobile viewport — input zoom behavior (iOS Safari `font-size < 16px`?)
210
+
211
+ Save: `.super-design/sessions/<id>/forms/<formId>_<scenario>.png`
212
+
213
+ ## Orchestration summary
214
+
215
+ sd-audit adds this between Step 2 and Step 3:
216
+
217
+ ```
218
+ Step 2.5 — Discovery
219
+ For each (page, viewport):
220
+ A. Interactive inventory
221
+ B. Modal/overlay enumeration (click every trigger)
222
+ C. Flow exercising (login, CRUD, checkout if applicable)
223
+ D. Component state matrix
224
+ E. Form state coverage
225
+ ```
226
+
227
+ This takes 3–5× longer than static-only audit but produces ~3× the findings,
228
+ each with real evidence of failure conditions (not just hypothetical WCAG
229
+ violations on static markup).
230
+
231
+ ## Budget & skipping
232
+
233
+ For very large apps, scope Phase B/C/D to:
234
+ - Top 5 most-clicked triggers per page (ranked by proximity to primary CTA)
235
+ - Critical flows only (login + checkout + 1 CRUD)
236
+ - 3 component classes minimum (Button, Input, Modal) — rest deferred to full-mode audit
237
+
238
+ Record what was skipped in `.super-design/sessions/<id>/scope.json` so later
239
+ runs can close the gap.
240
+
241
+ ## Error handling
242
+
243
+ - **Triggered modal doesn't appear within 2s** — record "trigger broken" finding, move on
244
+ - **Console error after click** — record verbatim, still capture whatever rendered
245
+ - **Focus not trapped** — record a11y violation
246
+ - **Modal close fails** — force navigate away, record "close broken" finding
247
+
248
+ Never let a broken trigger abort the full audit — isolate and continue.
249
+
250
+ ## Hard rules
251
+
252
+ 1. Every Phase A inventory item must be considered for exercising; skips recorded.
253
+ 2. Every modal opened must be screenshotted OPEN + CLOSED.
254
+ 3. Every flow must capture at least one error path, not just happy path.
255
+ 4. Component state matrix must declare which states are MISSING (not just captured).
256
+ 5. Form state coverage — 10 scenarios per form; partial completion records which.
257
+ 6. Use ONE Playwright session; reuse across phases; `browser_close` only at end.
258
+ 7. Sequential, not parallel. Never spawn parallel tabs.