free-pi-cli 0.6.3 → 0.6.4

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,251 @@
1
+ ---
2
+ name: ux-walker
3
+ description: Walk a UX story catalog (docs/ux-paths/catalog.md) through a real browser one story at a time, checking each journey for correctness, visual quality and UX. Looks at screenshots with look_at_image, measures alignment, spacing and wrapping with a geometry audit, and logs flow friction. Fixes small issues and writes up larger ones.
4
+ ---
5
+
6
+ # UX Walker
7
+
8
+ Walk each story in the catalog through a real browser. For every story, check that the
9
+ journey works, that the screens look right, and that the path is as short and clear as
10
+ it should be. Fix small problems on the spot. Write up larger ones.
11
+
12
+ This skill runs on your default model. Do not switch to a more expensive model. You
13
+ cannot see images directly: judge screenshots with the `look_at_image` tool (a cheap
14
+ vision model), and use DOM measurements for anything that can be measured.
15
+
16
+ Everything runs in one agent, in order. Walk one story, write its files, keep a
17
+ one-line summary in your head, then start the next. Do not try to hold several stories
18
+ in context. After a context reset, resume from the files in `docs/ux-walker/`.
19
+
20
+ ## When to use
21
+
22
+ "walk the stories", "test the ux paths", "ux walker", "verify user journeys", "qa the
23
+ user flows". Needs a catalog at `docs/ux-paths/catalog.md` (made by the ux-paths skill).
24
+
25
+ Options the user may give: a URL, `--full` (re-walk everything), `--focus <topic>`
26
+ (only that topic), `--session <name>` (reuse a browser session, keeps login). With no
27
+ arguments, detect the URL and start. Ask only if the app needs a login and you have no
28
+ test credentials.
29
+
30
+ `$SKILL_DIR` below means the folder that contains this SKILL.md.
31
+
32
+ ## Output
33
+
34
+ ```
35
+ docs/ux-walker/
36
+ run-history.json state across runs
37
+ walk-plan.json plan for the current run
38
+ latest-report.md final report
39
+ issues-filed.md every issue written up
40
+ issues/<finding-id>.md issue files when gh is not available
41
+ shots/STORY-NNN/ screenshots (must stay inside the project folder)
42
+ stories/STORY-NNN/walk-report.md what happened at each step
43
+ stories/STORY-NNN/findings.json findings for the story
44
+ fixes/<finding-id>.md one note per quick fix
45
+ ```
46
+
47
+ Screenshots must be saved inside the project folder, or look_at_image refuses them.
48
+
49
+ ## Step 0: Preflight
50
+
51
+ 1. **Browser tool.** `command -v agent-browser`. If missing, use `npx -y agent-browser`
52
+ everywhere below instead. On first use run `agent-browser install` (or
53
+ `npx -y agent-browser install`) once. Command patterns: `references/action-patterns.md`.
54
+ 2. **URL.** `curl -s -o /dev/null -w "%{http_code}" <url>`. If nothing answers, find the
55
+ dev command in package.json (or the README), start it in the background with a log
56
+ and a saved PID (`nohup <cmd> > docs/ux-walker/dev.log 2>&1 & echo $! > docs/ux-walker/dev.pid`),
57
+ pick a free port, wait for it once, and stop only that PID at the end. If you saved browser login state, delete `"${TMPDIR:-/tmp}/free-pi-ux-browser-state.json"` too.
58
+ 3. **Catalog.** If `docs/ux-paths/catalog.md` is missing, stop and tell the user to run
59
+ the ux-paths skill first.
60
+ 4. **Folders.** `mkdir -p docs/ux-walker/stories docs/ux-walker/shots docs/ux-walker/fixes`. Before a story's
61
+ first screenshot, also run `mkdir -p docs/ux-walker/shots/STORY-NNN` (agent-browser does not create it).
62
+ 5. **Run history.** Load `docs/ux-walker/run-history.json`, or start with
63
+ `{"runs": [], "stories": {}}`. Each story entry: `last_walked`, `status`
64
+ (pass or fail), `findings_count`, `source_files_hash`, `fixes_merged_since`.
65
+ 6. **Session.** Use `S=ux-walker-<domain>` (or the user's `--session`). Open the app:
66
+ `agent-browser --session $S open <url>` then `agent-browser --session $S wait --load networkidle`
67
+ (for apps with live connections, wait for a known element instead).
68
+ 7. **Version check (optional).** `curl -s <url>/__version` or `<url>/version.json`. If it
69
+ returns a git SHA that differs from `git rev-parse --short HEAD`, note that you may
70
+ be testing an older build and continue.
71
+
72
+ ## Step 1: Plan the walk
73
+
74
+ Read the catalog once. Write `docs/ux-walker/walk-plan.json` with one entry per story:
75
+ `{id, action, reason}`. Decide each action:
76
+
77
+ - `--full`: all stories are `walk`. `--focus topic`: only matching stories.
78
+ - Never walked: `walk`.
79
+ - Passed before and relevant source files unchanged since (`git log --since` on the
80
+ files the story touches, or compare `source_files_hash`): `skip`.
81
+ - Passed before but source changed: `re-verify`.
82
+ - Failed before and fixes made since: `re-verify`. Failed with no fixes: `walk`.
83
+
84
+ Tell the user the counts (walk, re-verify, skip), then start.
85
+
86
+ ## Step 2: Walk the stories, one at a time
87
+
88
+ Read `references/ux-audit-rubric.md` and `references/visual-inspection.md` once before
89
+ the first story. For each story in the plan, in order:
90
+
91
+ ### 2a. Walk
92
+
93
+ A story in the catalog has: Type, Topic, Persona, Goal, Preconditions, Steps,
94
+ Variations, Edge Cases, and sometimes an Ideal path. Use these fields as written.
95
+
96
+ For each step:
97
+ 1. `agent-browser --session $S snapshot -i`, find the target by text or role, act
98
+ (`click @e3`, `fill @e2 "..."`, `open <url>`). See `references/action-patterns.md`.
99
+ 2. Screenshot into `docs/ux-walker/shots/STORY-NNN/step-N.png`.
100
+ 3. Check the step's expected result from the snapshot or `get text` / `get url`.
101
+ 4. At each **distinct page state** (a new page or a major layout change, not every
102
+ click): run the geometry audit, then make one look_at_image call (below).
103
+ 5. Check `agent-browser --session $S errors` now and then. Console errors and failed
104
+ requests often explain visible problems.
105
+
106
+ **Geometry audit** (measure first):
107
+ ```bash
108
+ agent-browser --session $S eval --stdin < "$SKILL_DIR/references/geometry-audit.js"
109
+ ```
110
+ It reports uneven sibling rows, overflow spills, wrapped controls and page horizontal
111
+ overflow. Confirm each hit before logging it.
112
+
113
+ **look_at_image** (one call per distinct page state, one specific question):
114
+ ```
115
+ look_at_image(path="docs/ux-walker/shots/STORY-007/step-3.png",
116
+ question="<the look-pass question from references/visual-inspection.md, trimmed to this screen>")
117
+ ```
118
+ Each call uses part of the user's daily allowance. Do not call it for every step, do
119
+ not ask about the same image twice, and do not use it to measure. The answer comes
120
+ from another model and can be wrong: check any layout claim with `get box` or the
121
+ geometry audit before you log it.
122
+
123
+ **Responsive spot-check**, once per story at its main screen (skip for desktop-only
124
+ apps): `set viewport 390 844`, screenshot, run the geometry audit, `set viewport 1280 800`.
125
+ Only spend a look_at_image call if the audit reports something or the page looks odd.
126
+
127
+ **Audit the page state** against `references/ux-audit-rubric.md`: simplicity,
128
+ progressive disclosure, layout, visual correctness and consistency, hierarchy (one
129
+ clear primary action, nothing said twice), typography, feedback, error states, text
130
+ fit, accessibility basics. Ask "what could be removed without losing function?"
131
+
132
+ **Flow log** (write it as the last section of walk-report.md):
133
+ - Steps the story specified versus steps you actually needed. If the catalog has an
134
+ Ideal path and you needed more steps, log a `flow` finding naming the friction.
135
+ - Each moment the persona would hesitate (control not found in the first snapshot,
136
+ ambiguous label, unexpected navigation): a discoverability finding.
137
+ - Data the user re-enters that the app already knows: a `flow` finding.
138
+ - Information or controls shown on more than one screen: note it in the log.
139
+
140
+ If a step fails (element missing, unexpected state): screenshot, record the failure,
141
+ try to recover (back, reload), continue the remaining steps, and mark the story `fail`.
142
+
143
+ For an interaction bug that a still image cannot show, record a short video:
144
+ `record start docs/ux-walker/shots/STORY-NNN/finding-N.webm`, repeat the steps with
145
+ `wait 1000` between them, `record stop`. For a static bug one screenshot is enough.
146
+
147
+ ### 2b. Write the files now
148
+
149
+ Before starting the next story, write:
150
+ - `stories/STORY-NNN/walk-report.md`: for each distinct screen, one sentence on what the
151
+ screenshot shows plus the geometry result ("clean" or the hits); end with the flow log.
152
+ - `stories/STORY-NNN/findings.json`: array of objects:
153
+ ```json
154
+ {"id": "F-007-001", "story_id": "STORY-007",
155
+ "severity": "critical|high|medium|low|suggestion",
156
+ "category": "simplicity|disclosure|layout|visual|consistency|hierarchy|flow|happy-path|a11y|error-handling",
157
+ "criterion": "which check failed", "score": "warn|fail",
158
+ "description": "", "expected": "", "actual": "",
159
+ "screenshot": "shots/STORY-007/finding-1.png",
160
+ "suggested_fix": "or null", "files_likely_involved": ["src/Foo.tsx"]}
161
+ ```
162
+ - Update the story's entry in `run-history.json`.
163
+
164
+ Every finding needs at least a screenshot path, and a measurement when the problem is
165
+ visual ("left edges differ by 7px"). Stories are a script, not a limit: log anything
166
+ else you notice. Do not read source code while walking. Read it only when you fix.
167
+
168
+ Keep only a one-line summary of the story in context ("STORY-007 fail, 3 findings:
169
+ 1 high, 2 low"), then triage that story's findings and move on.
170
+
171
+ ### 2c. Triage
172
+
173
+ Use `references/triage-rubric.md`. A finding is a **quick fix** only if it touches 2 or
174
+ fewer files, has an obvious fix, is low risk, and is medium severity or lower. Critical
175
+ and high findings, anything needing design thought, and anything touching 3 or more
176
+ files are written up as issues. Suggestions are only listed in the report. At most 10
177
+ quick fixes per run.
178
+
179
+ ### 2d. Fix (one at a time)
180
+
181
+ For each quick fix, in order:
182
+ 1. Read the relevant source files. Make the smallest change that resolves the finding.
183
+ Only edit files inside the project folder; if the page is served from somewhere else, write the
184
+ fix up as an issue instead.
185
+ No refactoring, no nearby "improvements".
186
+ 2. Run the project's build, type check or the nearest test (look in package.json).
187
+ 3. Commit only the files you changed, with `fix(ux): <finding-id> <short description>`.
188
+ Never `git add -A`. Work on the current branch unless the user says otherwise; if it
189
+ is the default branch, create a branch first. Do not push.
190
+ 4. Write `docs/ux-walker/fixes/<finding-id>.md`: what was wrong, what changed, build result.
191
+ 5. Re-check the fix in the browser (reload, repeat the step, run the geometry audit,
192
+ take a new screenshot). If it persists, revert your change and write it up as an issue.
193
+
194
+ If a fix breaks the build and you cannot repair it quickly, revert it and write an issue.
195
+
196
+ ### 2e. Write up larger issues
197
+
198
+ For each finding that is not a quick fix, use `references/issue-template.md`.
199
+
200
+ - If `command -v gh` succeeds and `gh auth status` passes: `gh issue create` with the
201
+ filled template (`--label ux-walker`; add other labels only if they exist).
202
+ - Otherwise save the filled template to `docs/ux-walker/issues/<finding-id>.md`.
203
+
204
+ Add a row to `docs/ux-walker/issues-filed.md`: issue (number or file), story, severity,
205
+ title, URL or path.
206
+
207
+ ## Step 3: Re-walk fixed stories
208
+
209
+ After all stories are done, re-walk only the steps that had fixed findings, one story at
210
+ a time, with a fresh screenshot and audit. Mark the story `pass` if all findings are
211
+ resolved, otherwise `fail` and note what remains. Update `run-history.json` with the
212
+ run totals (stories walked, skipped, re-verified, findings, fixes, issues, passed, failed).
213
+
214
+ ## Step 4: Report
215
+
216
+ Read the story files one at a time and build `docs/ux-walker/latest-report.md` from
217
+ `templates/latest-report-template.md`. Include:
218
+
219
+ 1. Run metadata (date, URL, session, counts).
220
+ 2. Findings by severity and by category.
221
+ 3. Quick fixes applied (finding, files, verified or not).
222
+ 4. Issues filed or saved (with paths or URLs).
223
+ 5. UX audit summary: patterns across stories and systemic issues. The same audit defect
224
+ on several screens is one systemic finding.
225
+ 6. Flow friction table (story, actual versus ideal steps, hesitations) and information
226
+ shown in more than one place. If flow or redundancy shows up in 3 or more stories,
227
+ recommend running the ux-flow skill.
228
+ 7. Top 5 recommendations.
229
+ 8. Stories still failing, with reasons.
230
+
231
+ Finish with a short summary to the user: stories walked, pass and fail counts, fixes
232
+ made (with commit SHAs), issues written, and the path to the report. State plainly
233
+ what you did not verify.
234
+
235
+ ## Error handling
236
+
237
+ | Situation | Action |
238
+ |-----------|--------|
239
+ | agent-browser cannot connect | Retry once. Run `agent-browser install` if the browser is missing. If it still fails, tell the user. |
240
+ | Step fails | Screenshot, recover, continue, mark the story `fail`. |
241
+ | look_at_image returns an error (daily allowance, rate limit) | Do not retry in a loop. Rely on the geometry audit and the snapshot for the rest of the run, say so in the report, and tell the user. |
242
+ | Fix breaks the build | Revert it and write an issue. |
243
+ | Catalog missing | Stop. Ask the user to run the ux-paths skill. |
244
+ | Nothing to walk | Report that all stories pass with no source changes. Suggest `--full`. |
245
+
246
+ ## Rules
247
+
248
+ - Never delete screenshots, videos or reports during a run.
249
+ - Use test accounts and test data only. Do not click destructive actions against real data.
250
+ - Write each story's files before starting the next story.
251
+ - Do not push, and do not merge to the default branch.
@@ -0,0 +1,75 @@
1
+ # Action patterns: story step to agent-browser command
2
+
3
+ All commands run through bash. Use `agent-browser --session $S <command>`.
4
+ Run `agent-browser <command> --help` if unsure; do not guess flags.
5
+
6
+ ## Core loop
7
+
8
+ 1. `snapshot -i` lists interactive elements with refs such as `@e3`.
9
+ 2. Act on a ref (or a CSS selector).
10
+ 3. Take a screenshot into the project folder.
11
+ 4. Verify the expected result (re-run `snapshot -i`, or `get text`, `get url`).
12
+
13
+ Refs go stale after navigation or large page changes. Take a fresh snapshot then.
14
+
15
+ ## Actions
16
+
17
+ | Story step | Command |
18
+ |---|---|
19
+ | Go to a URL | `agent-browser --session $S open <url>` |
20
+ | Back / forward / reload | `back`, `forward`, `reload` |
21
+ | Click a ref | `click @e3` |
22
+ | Click by visible text (no snapshot yet) | `find text "Sign in" click` |
23
+ | Click by role and name | `find role button --name "Save" click` |
24
+ | Type character by character | `type @e2 "hello"` |
25
+ | Replace a field value | `fill @e2 "hello"` |
26
+ | Fill by label | `find label "Email" fill "a@b.test"` |
27
+ | Choose a dropdown option | `select @e4 "Option A"` |
28
+ | Check / uncheck | `check @e5`, `uncheck @e5` |
29
+ | Press a key | `press Enter`, `press Escape`, `press Tab` |
30
+ | Hover | `hover @e6` |
31
+ | Scroll | `scroll down 400`, `scrollintoview @e7` |
32
+ | Wait for page | `wait --load networkidle` (live apps with websockets never go idle; use the next line) |
33
+ | Wait for text or element | `wait --text "Saved"`, `wait "#results"`, `wait 800` (ms) |
34
+ | Current URL / title | `get url`, `get title` |
35
+ | Element text | `get text @e3` |
36
+ | Element size and position | `get box <selector>` |
37
+ | Computed styles | `get styles <selector>` |
38
+ | Console errors | `errors`, `console` |
39
+ | Screenshot (viewport) | `screenshot docs/ux-walker/shots/<story>/step-1.png` |
40
+ | Screenshot (whole page) | `screenshot --full <path>` |
41
+ | Numbered labels on controls | `screenshot --annotate <path>` |
42
+ | Narrow / wide viewport | `set viewport 390 844`, `set viewport 1280 800` |
43
+ | Dark mode | `set media dark`, `set media light` |
44
+ | Save / restore login | `state save "${TMPDIR:-/tmp}/free-pi-ux-browser-state.json"`, `state load "${TMPDIR:-/tmp}/free-pi-ux-browser-state.json"` (kept outside the project because it holds cookies; never commit it; delete it at the end of the run) |
45
+ | Video of an interaction | `record start docs/ux-walker/shots/<story>/f1.webm`, act with `wait 1000` between steps, `record stop` |
46
+
47
+ Several commands can go in one bash call, joined with `&&`.
48
+
49
+ ## Run the audit script
50
+
51
+ ```bash
52
+ agent-browser --session $S eval --stdin < "$SKILL_DIR/references/geometry-audit.js"
53
+ ```
54
+
55
+ `$SKILL_DIR` is the folder that contains this skill's SKILL.md.
56
+
57
+ ## Common flows
58
+
59
+ Login: `snapshot -i`, `fill @e1 "<user>"`, `fill @e2 "<password>"`, `click @e3`,
60
+ `wait --load networkidle`, screenshot, then `state save` to the path above. Use only test accounts that
61
+ the project provides. Never type real credentials from the user's environment.
62
+
63
+ Modal: click the trigger, `wait 500`, `snapshot -i` (the modal is now in the tree),
64
+ screenshot, act, `snapshot -i` again to confirm it closed.
65
+
66
+ Form: `snapshot -i`, `fill` each field by ref, submit, `wait --text "<success text>"`.
67
+
68
+ Drag: `drag @e1 @e2`, then screenshot.
69
+
70
+ ## Pacing and recovery
71
+
72
+ - `wait 500` after clicks that animate; `wait 1000` after navigation or submit.
73
+ - If an action fails: screenshot, `snapshot -i`, then try once more (scroll into
74
+ view, wait, fresh snapshot). If it fails twice, log the failure and go to the next step.
75
+ - If `agent-browser` cannot start, run `npx -y agent-browser install` once and retry.
@@ -0,0 +1,82 @@
1
+ // Geometry audit — run via: agent-browser --session {S} eval "$(cat geometry-audit.js)"
2
+ // Returns JSON of measurable layout defects. Numbers beat eyeballs for evenness;
3
+ // use the screenshot to judge whether a reported violation actually matters.
4
+ (() => {
5
+ const sig = (e) => {
6
+ let s = e.tagName.toLowerCase();
7
+ if (e.id) s += '#' + e.id;
8
+ else if (typeof e.className === 'string' && e.className.trim())
9
+ s += '.' + e.className.trim().split(/\s+/).slice(0, 2).join('.');
10
+ const t = (e.textContent || '').trim().replace(/\s+/g, ' ').slice(0, 30);
11
+ return t ? s + ' "' + t + '"' : s;
12
+ };
13
+ const vis = (e) => {
14
+ const r = e.getBoundingClientRect();
15
+ if (r.width < 1 || r.height < 1) return false;
16
+ const cs = getComputedStyle(e);
17
+ return cs.visibility !== 'hidden' && cs.display !== 'none';
18
+ };
19
+ const firstClass = (e) =>
20
+ typeof e.className === 'string' ? (e.className.trim().split(/\s+/)[0] || '') : '';
21
+
22
+ const out = {
23
+ pageOverflowX: Math.max(0, document.documentElement.scrollWidth - window.innerWidth),
24
+ unevenRows: [], // similar siblings in one visual row with different shapes/gaps
25
+ overflowSpills: [], // content escaping its container
26
+ wrappedControls: [], // short button/tab/chip labels forced onto 2+ lines
27
+ };
28
+
29
+ // 1. Sibling uniformity: flex-row/grid containers whose children are structurally
30
+ // similar (same tag + first class) should share height, width, gap, and top edge.
31
+ for (const p of document.querySelectorAll('body *')) {
32
+ const cs = getComputedStyle(p);
33
+ const flexRow = cs.display.includes('flex') && cs.flexDirection.startsWith('row');
34
+ const grid = cs.display.includes('grid');
35
+ if (!flexRow && !grid) continue;
36
+ const kids = [...p.children].filter(vis);
37
+ if (kids.length < 2 || kids.length > 16) continue;
38
+ if (!kids.every((k) => k.tagName === kids[0].tagName && firstClass(k) === firstClass(kids[0]))) continue;
39
+ const rects = kids.map((k) => k.getBoundingClientRect());
40
+ const topDrift = Math.max(...rects.map((r) => r.top)) - Math.min(...rects.map((r) => r.top));
41
+ if (topDrift > 24) continue; // wrapped onto multiple rows — not one visual row
42
+ const hs = rects.map((r) => Math.round(r.height));
43
+ const ws = rects.map((r) => Math.round(r.width));
44
+ const sorted = [...rects].sort((a, b) => a.left - b.left);
45
+ const gaps = [];
46
+ for (let i = 1; i < sorted.length; i++) gaps.push(Math.round(sorted[i].left - sorted[i - 1].right));
47
+ const issue = {};
48
+ if (Math.max(...hs) - Math.min(...hs) > 8) issue.heights = hs;
49
+ if (flexRow && Math.max(...ws) - Math.min(...ws) > 8) issue.widths = ws;
50
+ if (gaps.length > 1 && Math.max(...gaps) - Math.min(...gaps) > 4) issue.gaps = gaps;
51
+ if (topDrift > 3) issue.topDriftPx = Math.round(topDrift);
52
+ if (Object.keys(issue).length)
53
+ out.unevenRows.push({ container: sig(p), children: kids.length, ...issue });
54
+ }
55
+
56
+ // 2. Overflow: element content wider than its box while overflow-x is visible.
57
+ for (const e of document.querySelectorAll('body *')) {
58
+ if (!vis(e) || e.clientWidth < 24) continue;
59
+ if (!getComputedStyle(e).overflowX.includes('visible')) continue;
60
+ if (e.scrollWidth > e.clientWidth + 4)
61
+ out.overflowSpills.push({ el: sig(e), spillPx: e.scrollWidth - e.clientWidth });
62
+ }
63
+
64
+ // 3. Wrapped controls: a short label on a block-ish control taking 2+ lines
65
+ // means the container is too narrow or the label too long for the layout.
66
+ for (const b of document.querySelectorAll('button, [role="button"], a, summary, [class*="tab"], [class*="chip"], [class*="badge"]')) {
67
+ if (!vis(b)) continue;
68
+ const cs = getComputedStyle(b);
69
+ if (cs.display === 'inline') continue; // prose links legitimately wrap
70
+ if (b.querySelector('br, svg, img')) continue;
71
+ const label = (b.textContent || '').trim();
72
+ if (!label || label.length > 40) continue;
73
+ const lh = parseFloat(cs.lineHeight) || parseFloat(cs.fontSize) * 1.4;
74
+ const contentH = b.clientHeight - parseFloat(cs.paddingTop) - parseFloat(cs.paddingBottom);
75
+ if (contentH > lh * 1.8) out.wrappedControls.push(sig(b));
76
+ }
77
+
78
+ for (const k of ['unevenRows', 'overflowSpills', 'wrappedControls']) {
79
+ if (out[k].length > 12) { out[k] = out[k].slice(0, 12); out[k + 'Truncated'] = true; }
80
+ }
81
+ return JSON.stringify(out);
82
+ })();
@@ -0,0 +1,110 @@
1
+ # GitHub Issue Template — UX Walker Findings
2
+
3
+ Use this for findings the triage rubric sends to an issue. File with `gh issue create` only if `gh` is installed and authenticated; otherwise save the filled template to `docs/ux-walker/issues/{FINDING_ID}.md`.
4
+
5
+ ## Template
6
+
7
+ ```markdown
8
+ ## Context
9
+
10
+ Found by ux-walker during **STORY-{STORY_ID}: "{STORY_TITLE}"**
11
+ - **Run date**: {ISO_DATE}
12
+ - **Step**: Step {STEP_NUMBER} — "{STEP_DESCRIPTION}"
13
+ - **URL at time of finding**: {CURRENT_URL}
14
+
15
+ ## Finding
16
+
17
+ **ID**: {FINDING_ID}
18
+ **Severity**: {SEVERITY}
19
+ **Category**: {CATEGORY}
20
+ **Rubric Criterion**: {CRITERION} ({SCORE})
21
+
22
+ ### Description
23
+ {DETAILED_DESCRIPTION}
24
+
25
+ ### Expected Behavior
26
+ {EXPECTED}
27
+
28
+ ### Actual Behavior
29
+ {ACTUAL}
30
+
31
+ ## Evidence
32
+
33
+ ### Screenshot
34
+ <!-- Attach or reference the screenshot -->
35
+ ![{FINDING_ID}]({SCREENSHOT_PATH})
36
+
37
+ ### Page Snapshot (if relevant)
38
+ <details>
39
+ <summary>Accessibility tree at time of finding</summary>
40
+
41
+ ```
42
+ {SNAPSHOT_EXCERPT}
43
+ ```
44
+
45
+ </details>
46
+
47
+ ## Suggested Approach
48
+
49
+ {SUGGESTED_FIX_OR_APPROACH}
50
+
51
+ ### Files Likely Involved
52
+ {FILES_LIST — bulleted list of file paths}
53
+
54
+ ### Estimated Complexity
55
+ - **Files to change**: {FILE_COUNT}
56
+ - **Regression risk**: {LOW|MEDIUM|HIGH}
57
+ - **Design input needed**: {YES|NO}
58
+
59
+ ## Related
60
+
61
+ - **Story**: STORY-{STORY_ID} in `docs/ux-paths/catalog.md`
62
+ - **Walk report**: `docs/ux-walker/stories/STORY-{STORY_ID}/walk-report.md`
63
+ - **Full findings**: `docs/ux-walker/stories/STORY-{STORY_ID}/findings.json`
64
+
65
+ ---
66
+ Filed by ux-walker
67
+ ```
68
+
69
+ ## Usage — gh CLI Command
70
+
71
+ ```bash
72
+ gh issue create \
73
+ --title "UX: {SHORT_DESCRIPTION}" \
74
+ --body "$(cat <<'EOF'
75
+ {FILLED_TEMPLATE}
76
+ EOF
77
+ )" \
78
+ --label "ux-walker"
79
+ ```
80
+
81
+ ## Field Reference
82
+
83
+ | Field | Source | Example |
84
+ |-------|--------|---------|
85
+ | `STORY_ID` | walk-plan.json | `STORY-014` |
86
+ | `STORY_TITLE` | catalog.md | `New user creates first workspace` |
87
+ | `ISO_DATE` | Current timestamp | `2026-03-20T14:30:00Z` |
88
+ | `STEP_NUMBER` | findings.json → step | `3` |
89
+ | `STEP_DESCRIPTION` | catalog.md step text | `Click "Create Workspace" button` |
90
+ | `CURRENT_URL` | agent-browser url output | `http://localhost:1420/workspaces` |
91
+ | `FINDING_ID` | findings.json → id | `F-014-003` |
92
+ | `SEVERITY` | findings.json → severity | `high` |
93
+ | `CATEGORY` | findings.json → category | `layout` |
94
+ | `CRITERION` | findings.json → criterion | `Viewport usage` |
95
+ | `SCORE` | findings.json → score | `fail` |
96
+ | `DETAILED_DESCRIPTION` | findings.json → description | Full narrative |
97
+ | `EXPECTED` | findings.json → expected | What should happen |
98
+ | `ACTUAL` | findings.json → actual | What actually happens |
99
+ | `SCREENSHOT_PATH` | findings.json → screenshot | Relative path |
100
+ | `SNAPSHOT_EXCERPT` | Saved snapshot output | Trimmed to relevant section |
101
+ | `SUGGESTED_FIX_OR_APPROACH` | findings.json → suggested_fix | Or "Needs design discussion" |
102
+ | `FILES_LIST` | findings.json → files_likely_involved | Bulleted paths |
103
+ | `FILE_COUNT` | Derived from files list | `4` |
104
+
105
+ ## Notes
106
+
107
+ - Keep issue titles under 70 characters
108
+ - Title format: `UX: {verb} {what}` — e.g., "UX: simplify workspace creation form"
109
+ - If no suggested approach is obvious, write "Needs design discussion — the current implementation {description of problem}."
110
+ - Always include the screenshot — it's the most valuable part for async review
@@ -0,0 +1,55 @@
1
+ # Triage rubric: quick fix or written issue
2
+
3
+ Decide for each finding after a story is walked.
4
+
5
+ ## Quick fix: ALL must be true
6
+
7
+ 1. Touches 2 or fewer source files.
8
+ 2. The fix is obvious (typo, CSS tweak, missing label, wrong color, spacing).
9
+ 3. Low regression risk.
10
+ 4. Can be done in under 15 minutes.
11
+ 5. Severity is medium or lower.
12
+
13
+ Examples: typo in a button; padding off by a few pixels; missing label or aria-label;
14
+ text overflow in one component; missing hover style; sibling cards with uneven
15
+ heights (`align-items: stretch`); wrapped button label (`white-space: nowrap`);
16
+ uneven gaps (use `gap`); inconsistent border radius.
17
+
18
+ ## Write an issue: ANY is true
19
+
20
+ - Touches 3 or more files.
21
+ - Needs design thought or changes a workflow or information structure.
22
+ - Could break other features.
23
+ - Severity is critical or high.
24
+ - Restructures components or changes state handling.
25
+ - Needs a feature that does not exist.
26
+
27
+ Examples: confusing navigation; a 15-field form that should be progressive; raw API
28
+ errors shown to users; missing loading states across the app; broken mobile layout;
29
+ no keyboard support.
30
+
31
+ ## Overrides
32
+
33
+ - Critical findings are always written up, even if the fix looks easy.
34
+ - Suggestions are never fixed or filed. They go in the report only.
35
+ - At most 10 quick fixes per run. Further findings become issues (a sign of a
36
+ systemic problem).
37
+
38
+ ## Checklist
39
+
40
+ ```
41
+ 1. Severity medium or lower? no -> issue
42
+ 2. 2 files or fewer? no -> issue
43
+ 3. Solution obvious? no -> issue
44
+ 4. Low regression risk? no -> issue
45
+ 5. Fewer than 10 quick fixes so far? no -> issue
46
+ All yes -> quick fix
47
+ ```
48
+
49
+ ## Where issues go
50
+
51
+ If `command -v gh` finds GitHub CLI and `gh auth status` succeeds, file with
52
+ `gh issue create` (see issue-template.md). Otherwise write each issue as a markdown
53
+ file in `docs/ux-walker/issues/<finding-id>.md` using the same template, and list them
54
+ in `docs/ux-walker/issues-filed.md`. Labels: `ux-walker` plus the severity; add other
55
+ labels only if they already exist in the repo.