@tamsensedev/runner 0.13.0 → 0.18.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 (82) hide show
  1. package/LICENSE +5 -5
  2. package/README.md +61 -57
  3. package/dist/cli.js +646 -315
  4. package/dist/cli.js.map +1 -1
  5. package/dist/recorder.cjs.map +1 -1
  6. package/library/.claude-plugin/plugin.json +5 -5
  7. package/library/THIRD_PARTY_NOTICES.md +123 -123
  8. package/library/agents/code-architect.md +67 -67
  9. package/library/agents/code-explorer.md +61 -61
  10. package/library/agents/code-reviewer.md +73 -73
  11. package/library/agents/code-simplifier.md +62 -62
  12. package/library/agents/design-critic.md +52 -52
  13. package/library/agents/second-opinion.md +64 -64
  14. package/library/agents/security-auditor.md +86 -86
  15. package/library/agents/silent-failure-hunter.md +70 -70
  16. package/library/agents/test-coverage-analyzer.md +78 -78
  17. package/library/agents/test-runner.md +48 -48
  18. package/library/agents/ui-tester.md +50 -50
  19. package/library/licenses/Apache-2.0.txt +202 -202
  20. package/library/skills/accessibility/SKILL.md +144 -144
  21. package/library/skills/accessibility/references/wcag-checks.md +168 -168
  22. package/library/skills/addressing-review-feedback/SKILL.md +109 -109
  23. package/library/skills/app-screens/SKILL.md +96 -96
  24. package/library/skills/app-screens/references/shell-kpis-charts.md +108 -108
  25. package/library/skills/app-screens/references/states-density-phone.md +54 -54
  26. package/library/skills/app-screens/references/tables-forms-settings.md +104 -104
  27. package/library/skills/avoiding-generic-ai-design/SKILL.md +92 -92
  28. package/library/skills/avoiding-generic-ai-design/references/tells.md +112 -112
  29. package/library/skills/clean-commits/SKILL.md +85 -85
  30. package/library/skills/design-review/SKILL.md +107 -107
  31. package/library/skills/design-review/references/critique-passes.md +101 -101
  32. package/library/skills/design-review/references/screenshot-procedure.md +121 -121
  33. package/library/skills/differential-security-review/LICENSE +427 -427
  34. package/library/skills/differential-security-review/SKILL.md +105 -105
  35. package/library/skills/differential-security-review/references/adversarial.md +115 -115
  36. package/library/skills/differential-security-review/references/methodology.md +145 -145
  37. package/library/skills/differential-security-review/references/patterns.md +108 -108
  38. package/library/skills/false-positive-check/LICENSE +427 -427
  39. package/library/skills/false-positive-check/SKILL.md +95 -95
  40. package/library/skills/false-positive-check/references/bug-class-verification.md +128 -128
  41. package/library/skills/false-positive-check/references/deep-verification.md +113 -113
  42. package/library/skills/false-positive-check/references/evidence-templates.md +93 -93
  43. package/library/skills/false-positive-check/references/false-positive-patterns.md +122 -122
  44. package/library/skills/false-positive-check/references/gate-reviews.md +36 -36
  45. package/library/skills/false-positive-check/references/standard-verification.md +80 -80
  46. package/library/skills/focused-implementation/SKILL.md +104 -104
  47. package/library/skills/implementation-plan/SKILL.md +66 -66
  48. package/library/skills/interface-design/SKILL.md +144 -144
  49. package/library/skills/interface-design/references/craft-defaults.md +130 -130
  50. package/library/skills/interface-design/references/new-direction.md +62 -62
  51. package/library/skills/interface-design/references/writing.md +52 -52
  52. package/library/skills/interface-polish/SKILL.md +103 -103
  53. package/library/skills/interface-polish/references/detail-rules.md +154 -154
  54. package/library/skills/interface-polish/references/worst-case-data.md +158 -158
  55. package/library/skills/motion-design/SKILL.md +106 -106
  56. package/library/skills/motion-design/references/recipes.md +243 -243
  57. package/library/skills/postgres-performance/SKILL.md +97 -97
  58. package/library/skills/postgres-performance/references/rules.md +265 -265
  59. package/library/skills/project-orientation/SKILL.md +77 -77
  60. package/library/skills/reviewing-changes/SKILL.md +183 -183
  61. package/library/skills/safe-database-changes/SKILL.md +111 -111
  62. package/library/skills/safe-database-changes/references/backfills.md +75 -75
  63. package/library/skills/safe-database-changes/references/migration-tools.md +69 -69
  64. package/library/skills/safe-database-changes/references/postgres-ddl.md +199 -199
  65. package/library/skills/security-review/SKILL.md +132 -132
  66. package/library/skills/security-review/references/checks-by-area.md +107 -107
  67. package/library/skills/security-review/references/do-not-report.md +86 -86
  68. package/library/skills/spec-writing/SKILL.md +144 -144
  69. package/library/skills/systematic-debugging/SKILL.md +130 -130
  70. package/library/skills/systematic-debugging/references/flaky-tests.md +51 -51
  71. package/library/skills/systematic-debugging/references/root-cause-tracing.md +55 -55
  72. package/library/skills/task-interview/SKILL.md +84 -84
  73. package/library/skills/test-driven-development/SKILL.md +116 -116
  74. package/library/skills/test-driven-development/references/writing-good-tests.md +85 -85
  75. package/library/skills/ui-testing/SKILL.md +102 -102
  76. package/library/skills/ui-testing/references/headless-check.md +295 -295
  77. package/library/skills/ui-testing/references/local-stand.md +51 -51
  78. package/library/skills/ui-testing/references/playwright-patterns.md +134 -134
  79. package/library/skills/ui-testing/references/recording.md +61 -61
  80. package/library/skills/verification-before-completion/SKILL.md +113 -113
  81. package/library/skills/web-interface-guidelines/SKILL.md +202 -202
  82. package/package.json +46 -46
@@ -1,144 +1,144 @@
1
- ---
2
- name: accessibility
3
- description: Use when building or reviewing web UI people interact with (forms, buttons, links, dialogs, menus, tabs, images, colour, focus, keyboard handling, dynamic messages) or when a task mentions accessibility, a11y, WCAG or screen readers. Checks WCAG 2.2 AA from the code without a browser, plus an optional headless axe scan and keyboard pass.
4
- ---
5
-
6
- # Accessibility (WCAG 2.2 AA)
7
-
8
- Most accessibility bugs are visible in the code: a clickable `div`, an icon button with no name, an input without a label, a removed focus outline, an error shown only in red. This skill finds them in the changed UI, works without a browser, and adds an automated scan and a keyboard pass when a headless browser is available.
9
-
10
- The project's own rules come first: its component library (which may already handle focus and ARIA), its lint rules (`eslint-plugin-jsx-a11y`, `eslint-plugin-vuejs-accessibility`, Svelte's compiler warnings, Angular's template checks), its tests and any stated conformance target. Visual design rules are covered by the `web-interface-guidelines` and `design-review` skills; this skill does not repeat them.
11
-
12
- ## Process
13
-
14
- ### 1. Scope
15
-
16
- List the UI the change touches: components, templates, styles, routes. Include states the change adds (loading, empty, error, disabled, expanded) and anything that appears on top (dialogs, menus, toasts, tooltips).
17
-
18
- ### 2. Check the code
19
-
20
- Go through the list below for every changed component. Examples are plain HTML; the same rules apply to JSX, Vue, Svelte and Angular templates (`htmlFor` in React, `:aria-label` bindings in Vue, and so on). Full criteria and longer patterns: [references/wcag-checks.md](references/wcag-checks.md).
21
-
22
- **Names and semantics (1.1.1, 1.3.1, 2.4.4, 4.1.2)**
23
-
24
- - Use native elements: `<button>` for actions, `<a href>` for navigation, `<input>`, `<select>`, `<dialog>`. A `div` with a click handler is not focusable and does not respond to Enter or Space.
25
- - Every interactive element has an accessible name: visible text, `aria-label` or `aria-labelledby`. Icon-only buttons need one; the icon itself gets `aria-hidden="true"`.
26
- - The visible label is part of the accessible name (2.5.3): a button showing "Save" must not be labelled "Submit form".
27
- - Images: meaningful ones get alt text that says what matters; decorative ones get `alt=""`.
28
- - Link text makes sense out of context ("Download invoice", not "click here").
29
- - Headings follow the page structure without skipping levels for styling; lists are lists; data tables have `<th>` with scope or headers.
30
-
31
- Wrong, then right:
32
-
33
- ```html
34
- <div class="icon-btn" onclick="remove()"><svg>...</svg></div>
35
-
36
- <button type="button" aria-label="Remove item"><svg aria-hidden="true">...</svg></button>
37
- ```
38
-
39
- **Keyboard and focus (2.1.1, 2.1.2, 2.4.3, 2.4.7, 2.4.11)**
40
-
41
- - Everything a mouse can do, the keyboard can do. Custom widgets (menus, tabs, comboboxes, sliders) follow the WAI-ARIA Authoring Practices key patterns, or better, come from the project's component library.
42
- - No traps: Tab and Shift+Tab can leave every component; dialogs trap focus only while open and Escape closes them.
43
- - Focus order follows the visual order. No positive `tabindex`.
44
- - Focus is managed: opening a dialog moves focus into it, closing returns it to the trigger; deleting an item moves focus somewhere sensible; client-side route changes move focus to the new content or its heading.
45
- - Focus is visible. `outline: none` without a replacement style is a bug. Use `:focus-visible` with a style that contrasts at least 3:1 with its background.
46
- - Sticky headers, footers and banners do not cover the focused element (`scroll-margin` or `scroll-padding` helps).
47
-
48
- **Colour and contrast (1.4.1, 1.4.3, 1.4.11)**
49
-
50
- - Text contrast at least 4.5:1; large text (at least 24 px, or 18.66 px bold) at least 3:1.
51
- - Control boundaries, focus indicators, icons that carry meaning and chart elements at least 3:1 against what is next to them.
52
- - Colour is never the only signal: errors also get text or an icon, links in body text are underlined or otherwise distinct, chart series also differ by label or pattern.
53
- - Check placeholder text, disabled-looking text that is still important, and text over images or gradients. Compute contrast from the design tokens when you can; say when you estimated.
54
-
55
- **Forms and errors (1.3.5, 3.3.1, 3.3.2, 3.3.3, 3.3.7, 3.3.8)**
56
-
57
- - Every input has a programmatic label (`<label for>` or a wrapping label). A placeholder is not a label.
58
- - Personal data fields have the right `autocomplete` value (`email`, `name`, `current-password`, `new-password`, `one-time-code`).
59
- - Errors: text next to the field that says what is wrong and how to fix it, linked with `aria-describedby`, the field marked `aria-invalid="true"`, and focus moved to the first invalid field (or an error summary) on submit.
60
- - Required fields are marked in text, not only with colour or an asterisk without explanation.
61
- - Do not block paste in password or code fields, and offer password manager friendly fields (3.3.8). Do not ask again for data the user already entered in the same flow (3.3.7).
62
-
63
- ```html
64
- <label for="email">Email</label>
65
- <input id="email" type="email" autocomplete="email"
66
- aria-invalid="true" aria-describedby="email-error">
67
- <p id="email-error">Enter an email address like name@example.com.</p>
68
- ```
69
-
70
- **Dynamic content (4.1.3)**
71
-
72
- - Status messages that appear without a focus change (saved, copied, 3 results, upload finished) are announced: put them in a `role="status"` (polite) or `role="alert"` (urgent, errors) region that exists in the page before the message is inserted.
73
- - Loading states say so in text, not only with a spinner.
74
-
75
- **Pointer, motion and timing (2.2.1, 2.3.1, 2.5.7, 2.5.8)**
76
-
77
- - Targets are at least 24 by 24 CSS pixels, or spaced so a 24 px circle around each does not overlap another (inline text links are exempt). Touch-first layouts usually want 44 px.
78
- - Anything done by dragging also works with single clicks or taps (move up and down buttons, a menu, an input).
79
- - Animations respect `prefers-reduced-motion`; nothing flashes more than three times a second; auto-playing media can be paused.
80
- - Time limits can be extended, and sessions warn before expiring.
81
-
82
- **Page level (2.4.1, 2.4.2, 3.1.1)**
83
-
84
- - `<html lang>` is set; each route has a descriptive `<title>` (single-page apps must update it).
85
- - Landmarks (`header`, `nav`, `main`, `footer`) and a skip link or equivalent let keyboard users bypass repeated navigation.
86
-
87
- **ARIA misuse (4.1.2)**
88
-
89
- - No ARIA is better than wrong ARIA. Flag `aria-label` on a `div` or `span` with no role, `aria-hidden="true"` on focusable elements or their parents, `role="button"` without keyboard handling, `aria-expanded` or `aria-selected` that never updates, and duplicate `id`s that break label references.
90
-
91
- ### 3. Run what the project already has
92
-
93
- Accessibility lint rules, component or E2E tests with axe, `pa11y` or Lighthouse CI configs, Storybook accessibility checks. Run them on the changed files or pages. Do not install new tools to do this.
94
-
95
- ### 4. Optional: scan and keyboard pass in a headless browser
96
-
97
- When the app can be started (see the `ui-testing` skill):
98
-
99
- - **axe:** the headless check in the `ui-testing` skill (its `references/headless-check.md`) runs axe-core on each page when the project already has the `axe-core` package. If the project has `@axe-core/playwright`, use it in its own tests instead. Never download axe or a browser just for this.
100
- - **Keyboard pass:** use the snippet in [references/wcag-checks.md](references/wcag-checks.md#keyboard-pass-in-a-headless-browser) as the check's `steps` to record the focus order, whether each focused element shows a visible focus style, and whether Escape closes the open dialog and focus returns. The pass is recorded for the task like any browser run: set the check's title to "Keyboard pass" and its purpose to what you checked.
101
-
102
- Automated tools find roughly a third of WCAG problems. Zero axe violations is not conformance; a violation in third-party markup you do not control is still worth naming, but separately.
103
-
104
- ### 5. Fix or report
105
-
106
- In a code step, fix with the smallest change that uses the project's components and patterns: a real `<button>` instead of a clickable `div`, a label, a focus style from the design tokens. Do not add ARIA to paper over the wrong element.
107
-
108
- In a review or test step, report. Rate each finding:
109
-
110
- - **Blocker:** someone cannot complete the flow (keyboard trap, unlabeled or unreachable control in a core flow, focus lost in a dialog, form errors not perceivable).
111
- - **Serious:** harder but possible (low contrast on body text, missing status announcements, no visible focus on some controls).
112
- - **Moderate:** friction (heading order, redundant alt text, small targets in secondary places).
113
-
114
- A test-step verdict fails on blockers in the changed flow, and on serious findings the change introduced.
115
-
116
- ## Report
117
-
118
- ```
119
- Accessibility: <checked from code | code + axe | code + axe + keyboard>
120
- Findings:
121
- - [Blocker] src/components/DeleteButton.vue:12 icon-only button has no accessible name (4.1.2). Fix: aria-label="Delete project", icon aria-hidden.
122
- - [Serious] ...
123
- Not checked: <screen reader output, real devices, pages behind login, and why>
124
- ```
125
-
126
- Mention WCAG criterion numbers so findings can be looked up, and say which findings were measured (axe, computed contrast) and which come from reading the code.
127
-
128
- ## Common mistakes
129
-
130
- - Adding `role="button"` and `tabindex="0"` to a `div` instead of using `<button>`.
131
- - `aria-label` that differs from the visible text, or labels like "button" and "icon".
132
- - Removing focus outlines for looks.
133
- - Treating a clean axe run as proof of accessibility.
134
- - Checking only the default state, not errors, loading and open dialogs.
135
- - Hiding content with `display: none` when it should stay available to screen readers (use a visually-hidden class), or leaving off-screen menus focusable.
136
-
137
- ## Done when
138
-
139
- - Every changed interactive element has a name, a role, keyboard support and visible focus.
140
- - Forms label inputs and explain errors in text tied to the field.
141
- - Colour is never the only signal and contrast meets AA where you could compute it.
142
- - Findings carry file, line, WCAG criterion, severity and a concrete fix; what could not be checked is listed.
143
-
144
- Adapted from addyosmani/web-quality-skills `skills/accessibility` (MIT, commit afa8da942115f2961fdbfa80807ea0b232ff6c00, Copyright (c) 2026 Addy Osmani). Changed: rewritten as a review process for unattended runs, framework-neutral notes added, DevTools MCP and Lighthouse steps replaced by optional headless axe and keyboard checks, large-text threshold corrected to 24 px or 18.66 px bold, severity rules for verdicts added.
1
+ ---
2
+ name: accessibility
3
+ description: Use when building or reviewing web UI people interact with (forms, buttons, links, dialogs, menus, tabs, images, colour, focus, keyboard handling, dynamic messages) or when a task mentions accessibility, a11y, WCAG or screen readers. Checks WCAG 2.2 AA from the code without a browser, plus an optional headless axe scan and keyboard pass.
4
+ ---
5
+
6
+ # Accessibility (WCAG 2.2 AA)
7
+
8
+ Most accessibility bugs are visible in the code: a clickable `div`, an icon button with no name, an input without a label, a removed focus outline, an error shown only in red. This skill finds them in the changed UI, works without a browser, and adds an automated scan and a keyboard pass when a headless browser is available.
9
+
10
+ The project's own rules come first: its component library (which may already handle focus and ARIA), its lint rules (`eslint-plugin-jsx-a11y`, `eslint-plugin-vuejs-accessibility`, Svelte's compiler warnings, Angular's template checks), its tests and any stated conformance target. Visual design rules are covered by the `web-interface-guidelines` and `design-review` skills; this skill does not repeat them.
11
+
12
+ ## Process
13
+
14
+ ### 1. Scope
15
+
16
+ List the UI the change touches: components, templates, styles, routes. Include states the change adds (loading, empty, error, disabled, expanded) and anything that appears on top (dialogs, menus, toasts, tooltips).
17
+
18
+ ### 2. Check the code
19
+
20
+ Go through the list below for every changed component. Examples are plain HTML; the same rules apply to JSX, Vue, Svelte and Angular templates (`htmlFor` in React, `:aria-label` bindings in Vue, and so on). Full criteria and longer patterns: [references/wcag-checks.md](references/wcag-checks.md).
21
+
22
+ **Names and semantics (1.1.1, 1.3.1, 2.4.4, 4.1.2)**
23
+
24
+ - Use native elements: `<button>` for actions, `<a href>` for navigation, `<input>`, `<select>`, `<dialog>`. A `div` with a click handler is not focusable and does not respond to Enter or Space.
25
+ - Every interactive element has an accessible name: visible text, `aria-label` or `aria-labelledby`. Icon-only buttons need one; the icon itself gets `aria-hidden="true"`.
26
+ - The visible label is part of the accessible name (2.5.3): a button showing "Save" must not be labelled "Submit form".
27
+ - Images: meaningful ones get alt text that says what matters; decorative ones get `alt=""`.
28
+ - Link text makes sense out of context ("Download invoice", not "click here").
29
+ - Headings follow the page structure without skipping levels for styling; lists are lists; data tables have `<th>` with scope or headers.
30
+
31
+ Wrong, then right:
32
+
33
+ ```html
34
+ <div class="icon-btn" onclick="remove()"><svg>...</svg></div>
35
+
36
+ <button type="button" aria-label="Remove item"><svg aria-hidden="true">...</svg></button>
37
+ ```
38
+
39
+ **Keyboard and focus (2.1.1, 2.1.2, 2.4.3, 2.4.7, 2.4.11)**
40
+
41
+ - Everything a mouse can do, the keyboard can do. Custom widgets (menus, tabs, comboboxes, sliders) follow the WAI-ARIA Authoring Practices key patterns, or better, come from the project's component library.
42
+ - No traps: Tab and Shift+Tab can leave every component; dialogs trap focus only while open and Escape closes them.
43
+ - Focus order follows the visual order. No positive `tabindex`.
44
+ - Focus is managed: opening a dialog moves focus into it, closing returns it to the trigger; deleting an item moves focus somewhere sensible; client-side route changes move focus to the new content or its heading.
45
+ - Focus is visible. `outline: none` without a replacement style is a bug. Use `:focus-visible` with a style that contrasts at least 3:1 with its background.
46
+ - Sticky headers, footers and banners do not cover the focused element (`scroll-margin` or `scroll-padding` helps).
47
+
48
+ **Colour and contrast (1.4.1, 1.4.3, 1.4.11)**
49
+
50
+ - Text contrast at least 4.5:1; large text (at least 24 px, or 18.66 px bold) at least 3:1.
51
+ - Control boundaries, focus indicators, icons that carry meaning and chart elements at least 3:1 against what is next to them.
52
+ - Colour is never the only signal: errors also get text or an icon, links in body text are underlined or otherwise distinct, chart series also differ by label or pattern.
53
+ - Check placeholder text, disabled-looking text that is still important, and text over images or gradients. Compute contrast from the design tokens when you can; say when you estimated.
54
+
55
+ **Forms and errors (1.3.5, 3.3.1, 3.3.2, 3.3.3, 3.3.7, 3.3.8)**
56
+
57
+ - Every input has a programmatic label (`<label for>` or a wrapping label). A placeholder is not a label.
58
+ - Personal data fields have the right `autocomplete` value (`email`, `name`, `current-password`, `new-password`, `one-time-code`).
59
+ - Errors: text next to the field that says what is wrong and how to fix it, linked with `aria-describedby`, the field marked `aria-invalid="true"`, and focus moved to the first invalid field (or an error summary) on submit.
60
+ - Required fields are marked in text, not only with colour or an asterisk without explanation.
61
+ - Do not block paste in password or code fields, and offer password manager friendly fields (3.3.8). Do not ask again for data the user already entered in the same flow (3.3.7).
62
+
63
+ ```html
64
+ <label for="email">Email</label>
65
+ <input id="email" type="email" autocomplete="email"
66
+ aria-invalid="true" aria-describedby="email-error">
67
+ <p id="email-error">Enter an email address like name@example.com.</p>
68
+ ```
69
+
70
+ **Dynamic content (4.1.3)**
71
+
72
+ - Status messages that appear without a focus change (saved, copied, 3 results, upload finished) are announced: put them in a `role="status"` (polite) or `role="alert"` (urgent, errors) region that exists in the page before the message is inserted.
73
+ - Loading states say so in text, not only with a spinner.
74
+
75
+ **Pointer, motion and timing (2.2.1, 2.3.1, 2.5.7, 2.5.8)**
76
+
77
+ - Targets are at least 24 by 24 CSS pixels, or spaced so a 24 px circle around each does not overlap another (inline text links are exempt). Touch-first layouts usually want 44 px.
78
+ - Anything done by dragging also works with single clicks or taps (move up and down buttons, a menu, an input).
79
+ - Animations respect `prefers-reduced-motion`; nothing flashes more than three times a second; auto-playing media can be paused.
80
+ - Time limits can be extended, and sessions warn before expiring.
81
+
82
+ **Page level (2.4.1, 2.4.2, 3.1.1)**
83
+
84
+ - `<html lang>` is set; each route has a descriptive `<title>` (single-page apps must update it).
85
+ - Landmarks (`header`, `nav`, `main`, `footer`) and a skip link or equivalent let keyboard users bypass repeated navigation.
86
+
87
+ **ARIA misuse (4.1.2)**
88
+
89
+ - No ARIA is better than wrong ARIA. Flag `aria-label` on a `div` or `span` with no role, `aria-hidden="true"` on focusable elements or their parents, `role="button"` without keyboard handling, `aria-expanded` or `aria-selected` that never updates, and duplicate `id`s that break label references.
90
+
91
+ ### 3. Run what the project already has
92
+
93
+ Accessibility lint rules, component or E2E tests with axe, `pa11y` or Lighthouse CI configs, Storybook accessibility checks. Run them on the changed files or pages. Do not install new tools to do this.
94
+
95
+ ### 4. Optional: scan and keyboard pass in a headless browser
96
+
97
+ When the app can be started (see the `ui-testing` skill):
98
+
99
+ - **axe:** the headless check in the `ui-testing` skill (its `references/headless-check.md`) runs axe-core on each page when the project already has the `axe-core` package. If the project has `@axe-core/playwright`, use it in its own tests instead. Never download axe or a browser just for this.
100
+ - **Keyboard pass:** use the snippet in [references/wcag-checks.md](references/wcag-checks.md#keyboard-pass-in-a-headless-browser) as the check's `steps` to record the focus order, whether each focused element shows a visible focus style, and whether Escape closes the open dialog and focus returns. The pass is recorded for the task like any browser run: set the check's title to "Keyboard pass" and its purpose to what you checked.
101
+
102
+ Automated tools find roughly a third of WCAG problems. Zero axe violations is not conformance; a violation in third-party markup you do not control is still worth naming, but separately.
103
+
104
+ ### 5. Fix or report
105
+
106
+ In a code step, fix with the smallest change that uses the project's components and patterns: a real `<button>` instead of a clickable `div`, a label, a focus style from the design tokens. Do not add ARIA to paper over the wrong element.
107
+
108
+ In a review or test step, report. Rate each finding:
109
+
110
+ - **Blocker:** someone cannot complete the flow (keyboard trap, unlabeled or unreachable control in a core flow, focus lost in a dialog, form errors not perceivable).
111
+ - **Serious:** harder but possible (low contrast on body text, missing status announcements, no visible focus on some controls).
112
+ - **Moderate:** friction (heading order, redundant alt text, small targets in secondary places).
113
+
114
+ A test-step verdict fails on blockers in the changed flow, and on serious findings the change introduced.
115
+
116
+ ## Report
117
+
118
+ ```
119
+ Accessibility: <checked from code | code + axe | code + axe + keyboard>
120
+ Findings:
121
+ - [Blocker] src/components/DeleteButton.vue:12 icon-only button has no accessible name (4.1.2). Fix: aria-label="Delete project", icon aria-hidden.
122
+ - [Serious] ...
123
+ Not checked: <screen reader output, real devices, pages behind login, and why>
124
+ ```
125
+
126
+ Mention WCAG criterion numbers so findings can be looked up, and say which findings were measured (axe, computed contrast) and which come from reading the code.
127
+
128
+ ## Common mistakes
129
+
130
+ - Adding `role="button"` and `tabindex="0"` to a `div` instead of using `<button>`.
131
+ - `aria-label` that differs from the visible text, or labels like "button" and "icon".
132
+ - Removing focus outlines for looks.
133
+ - Treating a clean axe run as proof of accessibility.
134
+ - Checking only the default state, not errors, loading and open dialogs.
135
+ - Hiding content with `display: none` when it should stay available to screen readers (use a visually-hidden class), or leaving off-screen menus focusable.
136
+
137
+ ## Done when
138
+
139
+ - Every changed interactive element has a name, a role, keyboard support and visible focus.
140
+ - Forms label inputs and explain errors in text tied to the field.
141
+ - Colour is never the only signal and contrast meets AA where you could compute it.
142
+ - Findings carry file, line, WCAG criterion, severity and a concrete fix; what could not be checked is listed.
143
+
144
+ Adapted from addyosmani/web-quality-skills `skills/accessibility` (MIT, commit afa8da942115f2961fdbfa80807ea0b232ff6c00, Copyright (c) 2026 Addy Osmani). Changed: rewritten as a review process for unattended runs, framework-neutral notes added, DevTools MCP and Lighthouse steps replaced by optional headless axe and keyboard checks, large-text threshold corrected to 24 px or 18.66 px bold, severity rules for verdicts added.