plugins/lisa-rails-agy/skills/exploratory-qa/SKILL.md
First-time-user exploratory QA walkthrough for web apps that FEEDS THE LIFECYCLE. Use when asked to experience an app the way a brand-new human user would — landing cold on the home page and clicking through to find anything confusing, broken, or hard to understand (human-facing jargon, contextless extracted data, machine-style labels, slow or unclear loads, late meaningful content, cramped or cut-off UI, inconsistent/non-standard UX, awkward scroll behavior, unclear affordances, dead-end flows that strand a user — e.g. a login page with no way to register or recover a password, or a primary action that drops the user into an incomplete/unsatisfiable state with no way to finish) across all breakpoints. Instead of writing a report file, it files every finding as a tracked work item via lisa:tracker-write (bugs and usability/UX issues). A `ready` parameter controls whether those tickets are created build-ready (auto-picked-up by lisa:intake) or left in the backlog for human triage (default). For gaps in the automated Playwright test suite, use the e2e-coverage-gaps skill instead.
npx skillsauth add codyswanngt/lisa exploratory-qaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Experience the app the way a brand-new human user would: land cold on the home page with no prior knowledge, then click through and actually try to use it — just like a real person. The goal is to surface anything confusing, broken, or hard to understand, and to do so at every breakpoint.
This is a usability/experience pass, not a test-coverage audit. It does not look at the Playwright
suite or hunt for coverage gaps — for that, use the e2e-coverage-gaps skill. Here, every finding is
filed as a tracked work item so it enters the Lisa lifecycle — no static report file.
target-url | env (first positional) — what to explore.ready=true|false — the build-ready state for the tickets this pass creates.
ready=true → created build-ready, so lisa:intake / the build-intake scanner auto-picks them up.ready=false (default) → created in the backlog (not build-ready) for a human to review and
promote into the queue.ready flag
(default false).tracker from
.lisa.config.json (local overrides global). If it is unset, stop and report that the tracker must
be configured (via /lisa:setup:jira / :github / :linear) before exploratory QA can file
findings — do not silently fall back to a report file.Click through the visible paths and actually attempt real tasks — a first-time user explores, makes mistakes, and tries the obvious thing. Cover at least these dimensions unless the user narrows scope:
snake_case, null/undefined, untranslated i18n keys), admin/database terms such as
"metadata", implementation identifiers such as slugs, unexplained domain jargon, unclear
button/menu names, and icons with no discernible meaning. If a heading, label, or field would make a
non-technical user ask "what does that mean?", file a usability/clarity ticket with plainer wording.Money Mention, Entity, Record) paired with values but no sentence,
source, category, or explanation of why the value matters. If a user cannot tell what a number,
fact, or field refers to without rereading the raw source, file a usability/clarity ticket to hide it
from the default UI or add context such as excerpts, labels, grouping, or provenance.Bug; otherwise file a usability Improvement.Bug; when it eventually
works but the path is confusing or roundabout, file a usability Improvement.Loading... / Connecting... with no progress, anything that feels slow or janky. Flag pages
where the browser reports loaded / complete but meaningful content arrives much later, or where
the visible shell appears quickly while the real task content remains missing. Capture user-perceived
timings: shell visible, first meaningful content, and stable/complete content. If the delay is
noticeable, file a usability/performance ticket even if the eventual content is correct.A screenshot glance misses controls clipped by a few pixels or pushed just past a container edge. At every width, in addition to looking, take DOM measurements via the browser automation tool (Playwright, Chrome MCP, etc.) and treat any of these as a finding:
document.documentElement.scrollWidth > clientWidth, or a
horizontal scrollbar on a container that should not scroll → accidental horizontal overflow.getBoundingClientRect() against the viewport and against each ancestor
that has overflow: hidden | clip | auto | scroll. If any edge of the control falls outside those
bounds, it is partially or fully clipped / unreachable — even when the page looks fine in a thumbnail.
This is exactly the case that gets missed: a submit/apply button whose right edge is cut off by its
filter card.scrollWidth > clientWidth (or that renders an
ellipsis) where the hidden text carries meaning — e.g. a select showing "Any CRD state" jammed into
its chevron, a label cut mid-word.Record which width(s) trigger each, the offending element, and a screenshot. A primary or
interactive control that is clipped, offscreen, or unreachable is a Bug, not merely an
Improvement — a user literally cannot see or click all of it.
document.readyState, first meaningful
route-specific content, and visually stable/full route content.A real first-time user creates, edits, and deletes things — exercise those flows when the environment is safe.
qa- or codex-.This skill does not write a report file. Every finding becomes a leaf work item created via
lisa:tracker-write (the vendor-neutral writer — it dispatches to the configured tracker and runs the
validation gate; never call a vendor *-write-* skill directly). Map each finding to a type:
| Finding | issue_type | build_ready |
|---------|--------------|---------------|
| User-visible bug (broken behavior) | Bug | the ready flag (default false) |
| Usability / UX / clarity issue | Improvement | the ready flag (default false) |
A control that is clipped, offscreen, or otherwise unreachable (per §5) counts as broken behavior
→ file it as a Bug, not an Improvement. Pure crowding/clarity with the control still fully usable
is an Improvement.
Each finding is a flat leaf (no children), so build_ready applies directly — pass it explicitly on
every create. Each ticket MUST be a complete spec (the validator rejects thin tickets):
Re-running a pass must not refile the same finding. Before creating a ticket, search the tracker for an
open ticket carrying a stable marker [lisa-exploratory-qa] <finding-key> in its body (the
<finding-key> is a stable slug of surface + symptom, e.g. settings-modal/horizontal-overflow@tablet).
If one exists, reference/update it instead of creating a duplicate; only create when none exists.
Match by the marker, never by title (titles get edited). A closed prior ticket does not suppress a
new one — a recurrence after a fix is a genuine regression.
No report file. Emit a concise in-session summary:
ready vs triage/backlog).ready flag (default: backlog for human triage).e2e-coverage-gaps.development
Use Expo DOM components to run web code in a webview on native and as-is on web. Migrate web code to native incrementally.
development
Guidelines for upgrading Expo SDK versions and fixing dependency issues
development
Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`).
tools
`@expo/ui/swift-ui` package lets you use SwiftUI Views and modifiers in your app.