qa-design
[Testing] Design system consistency & UX heuristics: live-token audit, BL-UI invariants, Nielsen's 10, Figma comparison.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
[Testing] Design system consistency & UX heuristics: live-token audit, BL-UI invariants, Nielsen's 10, Figma comparison.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Initialize / onboard this agentic-QA plugin onto a deployment. Installs deps, then asks the operator only what genuinely shapes the config — the environment NAME, the bug tracker (Jira / Azure Boards), the code host (GitHub / Azure Repos), and an auth preference per axis (PAT recommended, else browser/CLI login). Everything else — whether it is a native-platform or a CLIENT project, the client org, the contribution mode, the fork account — is DERIVED from the token + the filled env + a live module/repo scan. Writes project-profile.json + .env.<env> + .env.local + .mcp.json and verifies access. The whole point is to make /qa-fix route each bug to the RIGHT repo (client custom code vs native platform) and file to the RIGHT tracker. Use when standing the plugin up on a new machine or for a new customer.
Initialize / onboard this agentic-QA plugin onto a deployment. Installs deps, then asks the operator only what genuinely shapes the config — the environment NAME, the bug tracker (Jira / Azure Boards), the code host (GitHub / Azure Repos), and an auth preference per axis (PAT recommended, else browser/CLI login). Everything else — whether it is a native-platform or a CLIENT project, the client org, the contribution mode, the fork account — is DERIVED from the token + the filled env + a live module/repo scan. Writes project-profile.json + .env.<env> + .env.local + .mcp.json and verifies access. The whole point is to make /qa-fix route each bug to the RIGHT repo (client custom code vs native platform) and file to the RIGHT tracker. Use when standing the plugin up on a new machine or for a new customer.
[QA Methodology] Gather ALL fresh CI prerelease artifacts for a change (modules + platform + vc-frontend) and deploy them together to the test env (vc-deploy-dev@<TEST_ENV branch>) in ONE manifest update: resolve a tracker ticket's linked PRs across all repos (or an explicit --module/--platform/--theme/--pr set) → each PR's latest vc3prerelease build → minimal-diff repin of backend/packages.json (AzureBlob/BlobName + PlatformVersion) and theme/artifact.json → dry-run combined diff (default) or a gated deploy PR (direct same-repo when the account has write, else a fork PR) → --verify polls the env-branch pin + /api/platform/modules per target. Never merges (a human merges to deploy); writes route through gh's keyring token; prints the web-edit URL when it can't push. Unblocks /qa-test PR#N and /qa-verify-fix.
[QA Method] Triangulate each BL invariant against docs + live + source code, auto-apply confirmed changes to business-logic.md, and reconcile test-case coverage. Delegates the live axis to qa-testing-expert; runs the triangulation via ba-system-analyzer.
Bring up a local Virto Commerce stack (backend + storefront + DB + ES) via start-local, pinned to the ACTUAL deployed package manifest (vc-deploy-dev @ vcptcore-demo); optionally augment it with the module/PR versions a JIRA task needs. Use when asked to spin up / run / provision a local VC environment, reproduce a deployed env locally, or stand up an env to test a specific ticket.
[QA Method] Defect management lifecycle: JIRA Bug Workflow, triage, classification, report validation, verification protocol, defect metrics.
| name | qa-design |
| description | [Testing] Design system consistency & UX heuristics: live-token audit, BL-UI invariants, Nielsen's 10, Figma comparison. |
| argument-hint | component | page URL | flow name |
Terminal command:
/qa-design <component | page | flow>— see commands/qa-design.md. The command parses the argument, resolves audit scope from critical-ui-scope.md, and dispatchesui-ux-expert; this file is the methodology library it consults.
Validate design system consistency and run UX heuristic evaluations against the active Coffee theme tokens, BL-UI invariants, and Nielsen's 10 usability heuristics.
/qa-design ProductCard # Audit one component against the design system
/qa-design checkout flow # UX heuristic evaluation of a flow
/qa-design https://figma.com/... # Compare implementation vs Figma spec (see Figma section below)
Before any design audit, the agent must already be aware of:
business-logic.md Domain 15 (BL-UI-001..006) — the canonical UI invariants. A violation is a FAIL regardless of how the result looks.scripts/lib/measure-layout.ts — the helper that wraps every required measurement: CLS observer, spacing audit, alignment audit, overflow audit, touch-target audit, rect snapshot for shift detection, occlusion audit (BL-UI-007), text contrast audit (BL-UI-008, WCAG 1.4.3), non-text/icon contrast audit (nonTextContrastAuditSnippet, WCAG 1.4.11), focus-indicator audit (BL-UI-009), image aspect-ratio audit (BL-UI-010), sized-control token+aspect audit (sizedControlAuditSnippet, VCST-5413), alert-semantics audit (alertSemanticsAuditSnippet, WCAG 4.1.3), plus classifiers.048b-layout-stability.csv — the 18-case suite that drives BL-UI-001..006 against live storefront. Run via SUITE_SELECTION=layout-stability npm run ci:regression.measure-layout.ts but are not yet promoted into business-logic.md Domain 15 (which currently defines only BL-UI-001..006). Audit with them; cite them as PROPOSED-BL-UI-NNN until promoted. The non-text-contrast (icon/graphic, WCAG 1.4.11 — classifier invariant BL-UI-008-NONTEXT), sized-control (SIZED-CONTROL), and alert-semantics (WCAG-4.1.3) audits are newer additions covering gaps the text/occlusion snippets miss — cite them by their WCAG/VCST id.Delegate to ui-ux-expert via the Agent tool (subagent_type: ui-ux-expert). The skill itself does not run measurements — the agent does, using the canonical helper.
// browser_evaluate snippet — see design-system-consistency.md for the full version
const tokens = getRootCustomProperties(); // → { '--color-primary': '#…', '--spacing-md': '16px', … }
spacingAuditSnippet(selector) from measure-layout.ts, classify with classifySpacing(). Pin every finding to BL-UI-002.alignmentAuditSnippet(selector) + classifyAlignment(). Pin to BL-UI-005.var(--color-…), not a literal hex. Run contrastAuditSnippet(selector) + classifyContrast() to enforce 4.5:1 / 3:1 ratios. Pin to PROPOSED-BL-UI-008 (or BL-UI-008 once promoted). Toggle theme preset — literals don't move, tokens do; a contrast PASS on default may FAIL on a dark preset.
contrastAuditSnippet only sees TEXT nodes — it skips icons entirely. For any surface with icon glyphs, ALSO run nonTextContrastAuditSnippet(selector) + classifyNonTextContrast() (default selector targets svg / .vc-icon). It resolves each glyph's painted color (stroke for outline icons, fill for solid, else CSS color) vs background at the 3:1 minimum and exempts icons inside disabled/aria-disabled controls (WCAG 1.4.11 excludes inactive components — don't false-positive, per the VCST-5100 lesson). Cite WCAG 1.4.11 / classifier BL-UI-008-NONTEXT. This is the audit that catches the outline-first thin-muted-stroke regression (VCST-4400: enabled icons at 2.52:1).font-family family across surfaces, weights ∈ {400, 500, 600, 700}, body ≥ 14 px.LAYOUT_SNIPPETS.overflowAudit + LAYOUT_SNIPPETS.touchTargetAudit. Pin to BL-UI-004 and BL-UI-006.occlusionAuditSnippet() + classifyOcclusion() on any page that can render .vc-alert--danger / .vc-alert--warning / [role="alert"]. Mandatory whenever the State-Stress Pass (below) renders a disabled / error / unavailable state. Pin to PROPOSED-BL-UI-007. P0 if severe: true on any overlap. When the message lives OUTSIDE the default alert set (VCST-4400: the cart over-stock warning renders in div.vc-line-item__after), pass the custom container selector: occlusionAuditSnippet(['.vc-line-item__after', ...]).
role="alert"/status/aria-live is never announced to a screen reader. Run alertSemanticsAuditSnippet(selector) + classifyAlertSemantics() on suspected message slots (default targets .vc-alert--danger/--warning, line-item__after, [class*="error"]/[class*="warning"]). Advisory WARN — confirm the flagged element is a genuine status message before filing. Cite WCAG 4.1.3 / classifier WCAG-4.1.3. (Surfaced by VCST-4400: the over-stock message is not in a live region.)LAYOUT_SNIPPETS.focusIndicatorAudit + classifyFocusIndicator(). Mandatory on /sign-in, /sign-up, /cart, /checkout/payment (revenue-critical keyboard flows). Pin to PROPOSED-BL-UI-009. The snippet now skips disabled controls and separates confirmed missing from indeterminate (a programmatic .focus() often doesn't trigger :focus-visible, where themes put the ring). indeterminate items make the classifier return WARN, not FAIL — confirm them with a real keyboard-Tab pass before filing (a scripted focus that shows no ring is NOT proof of a missing ring; VCST-4400 hit 29 such false positives).imageAspectAuditSnippet(selector) + classifyImageAspect() on pages with product images, hero banners, logos, or CMS imagery. Pin to PROPOSED-BL-UI-010.The default render (signed-in happy-path) covers only ~30% of real-user states. Bugs frequently appear only when a page is in a non-default state — and invariant audits against the default state silently miss them. F-CART-006 (save-for-later icon covering "product no longer available" alert) was missed by a default-state-only audit because the alert only appears on disabled products.
For every page audit, enumerate and audit each applicable state separately:
| State | Trigger | Audits to re-run |
|---|---|---|
| Loading / skeleton | Throttle network (Fast 3G) or block xAPI response | BL-UI-001 (CLS), BL-UI-001 refinement (skeleton-count parity) |
| Empty | Sign in to account with no orders / wishlists / cart items | BL-UI-002 (empty-state copy spacing), BL-UI-006 (CTA size) |
| Error / disabled | Cart with a disabled / unavailable product (Capri-Sun, SHOT in vcst-qa); order with payment-failed status | BL-UI-007 occlusion (pass the message's own selector if outside the default alert set), WCAG 4.1.3 alert-semantics (is the warning announced?), BL-UI-004 overflow on alert text |
| Multi-item / overflow | Cart with 10+ line items; order with long product titles; address with long company name | BL-UI-004 overflow, BL-UI-005 alignment |
| Form-validation error | Submit form with invalid email / empty required / weak password | BL-UI-003 state-shift (validation message insertion), BL-UI-004 (long error text wrap) |
| Auth-required action when anonymous | Click "Place Order" / "Save list" while signed out | BL-UI-003 (modal insertion), BL-UI-006 (modal CTA size) |
| Dark theme | Toggle theme preset to a dark preset | BL-UI-008 text contrast, WCAG 1.4.11 non-text/icon contrast, BL-UI-009 focus visibility |
Skip a state only if the page cannot enter it (e.g., /sign-up has no "empty cart" state). When a state is skipped, record the reason in the report.
Snippets measure numeric thresholds. Some defects are obvious in a screenshot but trip no measurement:
/sign-in uses Coffee primary; same button on /checkout uses an off-spec hue).After running all invariant snippets, the agent must:
PROPOSED-BL-* if one applies.Visual-review findings are filed individually (one bug per defect) and should explicitly note "caught by visual review, not invariant snippet" so the methodology gap is visible — over time, recurring visual findings become candidates for new invariants.
Raw dimensions that clear a "≥ threshold / no-overflow" gate can still be wrong: a control can pass full-width, touch-target ≥ 44 px, and no-overflow while rendering the wrong shape or the wrong size. VCST-5413 (VcSlider price-filter handles rendering as 34×28 ovals instead of an 18×18 circle — nouislider's default .noUi-handle winning the storefront cascade over the component's size-[--handle-size]) passed every threshold gate and was missed on the first pass, because the oracle direction was wrong: the handle's 34×28 was in the measurement table the whole time, read as "just larger" instead of "off-token and non-square."
Helper: run sizedControlAuditSnippet(selector, opts) + classifySizedControl() from measure-layout.ts — it encodes the oracle below. opts.tokenVar resolves the expected px FROM the element (e.g. { tokenVar: '--handle-size' }), or pass opts.expectedPx; opts.square (default true) or opts.ratio sets the aspect check. Run it on BOTH surfaces and diff. Classifier invariant SIZED-CONTROL.
For any control with a declared size (slider handles, avatars, icon buttons, badges, thumbnails, chips, swatches, checkboxes/radios — anything backed by a --*-size token, size-[…], or an intended square / circle / fixed-ratio shape), the oracle is equality + aspect, not a lower bound:
getComputedStyle(el).width === <resolved --token> (e.g. --handle-size → 18 px). "Bigger is fine" is NOT acceptable; a size that drifts off its token is a FAIL to investigate, not a footnote.rect.width === rect.height; for a fixed-ratio control assert width / height === <intended ratio>. 34 !== 28 on a border-radius: 9999px box → oval → instant FAIL.evidence-capture-policy.md "final state if critical").ux-heuristic-evaluation.md (0 = not an issue, 4 = catastrophe). Promote one level on revenue-critical surfaces (checkout / payment / add-to-cart / registration).ux-heuristic-evaluation.md.Figma MCP integration is shaky in this project — the configured figma-remote-mcp only exposes authenticate / complete_authentication tools right now. If you need to compare against a Figma frame:
See "Recommended workflow" in the project conversation log (or ask /claude-code-guide for the current state of Claude Code ↔ Figma) for the up-to-date picture.
BL-UI-NNN or PROPOSED-BL-UI-NNN and the computed-style evidenceevidence-capture-policy.md) + baseline screenshots per viewport per state to support the Visual-Review Pass + one confirmation screenshot of each integrated sized control even on PASS (Sized-Control Measurement Pass)Audits produce 0–N findings. Decision tree for what to file:
| Pattern | What to file |
|---|---|
| One component, one violation | Individual bug via /qa-bug tagged with the violated BL-UI-NNN |
| One component, multiple violations | ONE bug per component listing all violations — don't fragment |
| Multiple components share the same violation (5+ components with off-token color, etc.) | ONE rollup bug describing the systemic drift. Title: Design System Drift — [violation type] across [N] components. Priority bumped to P1 |
| Token resolution itself is broken | P1 bug — the design system layer is broken, not the components |
| UX heuristic finding with severity 0–1 | Log in evaluation report, do not file individually |
| UX heuristic finding with severity 2 | File as P3 bug, include suggested improvement |
| UX heuristic finding with severity 3–4 | File as P0–P1 bug, escalate severity 4 to qa-lead-orchestrator |
PROPOSED-BL-UI-NNN; their audit logic lives in scripts/lib/measure-layout.ts until promoted into business-logic.md Domain 15.sizedControlAuditSnippet(selector, {tokenVar\|expectedPx, square\|ratio}) + classifySizedControl(): assert rendered === token and width === height (or the intended ratio); cross-check Storybook vs storefront (size drift between the two = cascade-override red flag); and capture one confirmation screenshot of the integrated control even on PASS.contrastAuditSnippet skips glyphs; run nonTextContrastAuditSnippet() (WCAG 1.4.11, 3:1, disabled-exempt) for any icon-bearing surface. A warning styled like an alert but with no role=alert/aria-live is unannounced — check with alertSemanticsAuditSnippet() (WCAG 4.1.3).focusIndicatorAudit indeterminate items (where :focus-visible didn't trigger) are WARN, not FAIL; confirm with a real keyboard-Tab pass before filing (VCST-4400 lesson).ui-ux-expert via the Agent tool (subagent_type: ui-ux-expert) — this skill is a methodology library, not an executor.