@tamsensedev/runner 0.10.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 (83) hide show
  1. package/LICENSE +5 -5
  2. package/README.md +61 -50
  3. package/dist/cli.js +1188 -324
  4. package/dist/cli.js.map +1 -1
  5. package/dist/recorder.cjs +42 -6
  6. package/dist/recorder.cjs.map +1 -1
  7. package/library/.claude-plugin/plugin.json +5 -5
  8. package/library/THIRD_PARTY_NOTICES.md +123 -123
  9. package/library/agents/code-architect.md +67 -67
  10. package/library/agents/code-explorer.md +61 -61
  11. package/library/agents/code-reviewer.md +73 -73
  12. package/library/agents/code-simplifier.md +62 -62
  13. package/library/agents/design-critic.md +52 -52
  14. package/library/agents/second-opinion.md +64 -64
  15. package/library/agents/security-auditor.md +86 -86
  16. package/library/agents/silent-failure-hunter.md +70 -70
  17. package/library/agents/test-coverage-analyzer.md +78 -78
  18. package/library/agents/test-runner.md +48 -48
  19. package/library/agents/ui-tester.md +50 -50
  20. package/library/licenses/Apache-2.0.txt +202 -202
  21. package/library/skills/accessibility/SKILL.md +144 -144
  22. package/library/skills/accessibility/references/wcag-checks.md +168 -168
  23. package/library/skills/addressing-review-feedback/SKILL.md +109 -109
  24. package/library/skills/app-screens/SKILL.md +96 -96
  25. package/library/skills/app-screens/references/shell-kpis-charts.md +108 -108
  26. package/library/skills/app-screens/references/states-density-phone.md +54 -54
  27. package/library/skills/app-screens/references/tables-forms-settings.md +104 -104
  28. package/library/skills/avoiding-generic-ai-design/SKILL.md +92 -92
  29. package/library/skills/avoiding-generic-ai-design/references/tells.md +112 -112
  30. package/library/skills/clean-commits/SKILL.md +85 -85
  31. package/library/skills/design-review/SKILL.md +107 -107
  32. package/library/skills/design-review/references/critique-passes.md +101 -101
  33. package/library/skills/design-review/references/screenshot-procedure.md +121 -121
  34. package/library/skills/differential-security-review/LICENSE +427 -427
  35. package/library/skills/differential-security-review/SKILL.md +105 -105
  36. package/library/skills/differential-security-review/references/adversarial.md +115 -115
  37. package/library/skills/differential-security-review/references/methodology.md +145 -145
  38. package/library/skills/differential-security-review/references/patterns.md +108 -108
  39. package/library/skills/false-positive-check/LICENSE +427 -427
  40. package/library/skills/false-positive-check/SKILL.md +95 -95
  41. package/library/skills/false-positive-check/references/bug-class-verification.md +128 -128
  42. package/library/skills/false-positive-check/references/deep-verification.md +113 -113
  43. package/library/skills/false-positive-check/references/evidence-templates.md +93 -93
  44. package/library/skills/false-positive-check/references/false-positive-patterns.md +122 -122
  45. package/library/skills/false-positive-check/references/gate-reviews.md +36 -36
  46. package/library/skills/false-positive-check/references/standard-verification.md +80 -80
  47. package/library/skills/focused-implementation/SKILL.md +104 -104
  48. package/library/skills/implementation-plan/SKILL.md +66 -66
  49. package/library/skills/interface-design/SKILL.md +144 -144
  50. package/library/skills/interface-design/references/craft-defaults.md +130 -130
  51. package/library/skills/interface-design/references/new-direction.md +62 -62
  52. package/library/skills/interface-design/references/writing.md +52 -52
  53. package/library/skills/interface-polish/SKILL.md +103 -103
  54. package/library/skills/interface-polish/references/detail-rules.md +154 -154
  55. package/library/skills/interface-polish/references/worst-case-data.md +158 -158
  56. package/library/skills/motion-design/SKILL.md +106 -106
  57. package/library/skills/motion-design/references/recipes.md +243 -243
  58. package/library/skills/postgres-performance/SKILL.md +97 -97
  59. package/library/skills/postgres-performance/references/rules.md +265 -265
  60. package/library/skills/project-orientation/SKILL.md +77 -77
  61. package/library/skills/reviewing-changes/SKILL.md +183 -183
  62. package/library/skills/safe-database-changes/SKILL.md +111 -111
  63. package/library/skills/safe-database-changes/references/backfills.md +75 -75
  64. package/library/skills/safe-database-changes/references/migration-tools.md +69 -69
  65. package/library/skills/safe-database-changes/references/postgres-ddl.md +199 -199
  66. package/library/skills/security-review/SKILL.md +132 -132
  67. package/library/skills/security-review/references/checks-by-area.md +107 -107
  68. package/library/skills/security-review/references/do-not-report.md +86 -86
  69. package/library/skills/spec-writing/SKILL.md +144 -144
  70. package/library/skills/systematic-debugging/SKILL.md +130 -130
  71. package/library/skills/systematic-debugging/references/flaky-tests.md +51 -51
  72. package/library/skills/systematic-debugging/references/root-cause-tracing.md +55 -55
  73. package/library/skills/task-interview/SKILL.md +84 -84
  74. package/library/skills/test-driven-development/SKILL.md +116 -116
  75. package/library/skills/test-driven-development/references/writing-good-tests.md +85 -85
  76. package/library/skills/ui-testing/SKILL.md +102 -102
  77. package/library/skills/ui-testing/references/headless-check.md +295 -280
  78. package/library/skills/ui-testing/references/local-stand.md +51 -51
  79. package/library/skills/ui-testing/references/playwright-patterns.md +134 -134
  80. package/library/skills/ui-testing/references/recording.md +61 -58
  81. package/library/skills/verification-before-completion/SKILL.md +113 -113
  82. package/library/skills/web-interface-guidelines/SKILL.md +202 -202
  83. 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.