agentic-a11y

SkillDev tools

Use when auditing a user-facing app — web, mobile (iOS/Android/React Native/Flutter), desktop, CLI, or games — for accessibility barriers or WCAG 2.2 conformance, before shipping UI changes, or in response to concerns about screen-reader, keyboard, low-vision, motor, cognitive, or photosensitive users. Not for general bug hunting or code correctness.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the agentic-a11y skill

What this skill tells your AI

The instructions your AI receives, as published by ovid/paad in plugins/paad/skills/agentic-a11y/SKILL.md and read by ahel’s review.

On invocation: announce "Running paad:agentic-a11y v1.31.0" before anything else.

Accessibility Audit

Multi-agent accessibility audit of user-facing code across any platform. Dispatches specialist agents in parallel — each focused on a different disability category — verifies findings to filter false positives, maps every issue to specific accessibility criteria, and produces a persistent report with concrete fix recommendations.

Conformance target: WCAG 2.2 AA as baseline (applied via WCAG2ICT for non-web platforms). AAA criteria are flagged as bonus recommendations. Platform-specific guidelines (Apple HIG Accessibility, Android Accessibility, Xbox Accessibility Guidelines) are referenced where applicable.

This is a technique skill. Follow the phases in order. Do not skip verification.

Pre-flight:

digraph preflight {
  "Conversation has history?" [shape=diamond];
  "User-facing code exists?" [shape=diamond];
  "Proceed to Phase 1" [shape=box];
  "STOP: recommend new session" [shape=box, style=bold];
  "STOP: no user-facing code" [shape=box, style=bold];

  "Conversation has history?" -> "STOP: recommend new session" [label="yes"];
  "Conversation has history?" -> "User-facing code exists?" [label="no"];
  "User-facing code exists?" -> "STOP: no user-facing code" [label="no"];
  "User-facing code exists?" -> "Proceed to Phase 1" [label="yes"];
}

Audit flow:

digraph audit_flow {
  "Scope size?" [shape=diamond];
  "Platform has framework-specific a11y pitfalls?" [shape=diamond];
  "Existing a11y tooling already catches it?" [shape=diamond];
  "Tooling misconfigured or finding suppressed?" [shape=diamond];
  "Barrier handled elsewhere?" [shape=diamond];
  "Confidence >= 60?" [shape=diamond];
  "Cited criterion correct?" [shape=diamond];
  "Reported by multiple specialists?" [shape=diamond];
  "AAA criterion?" [shape=diamond];

  "Detect platform(s), stack, tooling, steering files, manifest" [shape=box];
  "Partition files across 2 instances of each specialist" [shape=box];
  "Dispatch the 5 core specialists in parallel" [shape=box];
  "Dispatch the 5 core specialists + Platform-Specific Patterns in parallel" [shape=box];
  "DROP the finding" [shape=box];
  "Correct the criterion" [shape=box];
  "Assign severity: critical / serious / moderate / minor" [shape=box];
  "Merge duplicates, note the agreeing specialists" [shape=box];
  "List under Minor Issues & AAA Recommendations, prefix [AAA]" [shape=box];
  "Place under its severity section" [shape=box];
  "Write report to paad/a11y-reviews/a11y-<timestamp>.md" [shape=box];
  "Report location, counts by severity, Quick Wins guidance" [shape=box];
  "STOP: report is the deliverable — do NOT auto-fix" [shape=box, style=bold];

  "Detect platform(s), stack, tooling, steering files, manifest" -> "Scope size?";
  "Scope size?" -> "Platform has framework-specific a11y pitfalls?" [label="small (<20) / medium (20-100)"];
  "Scope size?" -> "Partition files across 2 instances of each specialist" [label="large (100+ user-facing files)"];
  "Partition files across 2 instances of each specialist" -> "Platform has framework-specific a11y pitfalls?";
  "Platform has framework-specific a11y pitfalls?" -> "Dispatch the 5 core specialists + Platform-Specific Patterns in parallel" [label="yes"];
  "Platform has framework-specific a11y pitfalls?" -> "Dispatch the 5 core specialists in parallel" [label="no"];
  "Dispatch the 5 core specialists in parallel" -> "Existing a11y tooling already catches it?";
  "Dispatch the 5 core specialists + Platform-Specific Patterns in parallel" -> "Existing a11y tooling already catches it?";

  "Existing a11y tooling already catches it?" -> "Tooling misconfigured or finding suppressed?" [label="yes — specialists check this"];
  "Existing a11y tooling already catches it?" -> "Barrier handled elsewhere?" [label="no"];
  "Tooling misconfigured or finding suppressed?" -> "DROP the finding" [label="no — do not re-flag what tooling already catches"];
  "Tooling misconfigured or finding suppressed?" -> "Barrier handled elsewhere?" [label="yes"];
  "Barrier handled elsewhere?" -> "DROP the finding" [label="yes — parent, platform API, framework, library, system setting (verifier)"];
  "Barrier handled elsewhere?" -> "Confidence >= 60?" [label="no"];
  "Confidence >= 60?" -> "DROP the finding" [label="no"];
  "Confidence >= 60?" -> "Cited criterion correct?" [label="yes"];
  "Cited criterion correct?" -> "Assign severity: critical / serious / moderate / minor" [label="yes"];
  "Cited criterion correct?" -> "Correct the criterion" [label="no"];
  "Correct the criterion" -> "Assign severity: critical / serious / moderate / minor";
  "Assign severity: critical / serious / moderate / minor" -> "Reported by multiple specialists?";
  "Reported by multiple specialists?" -> "Merge duplicates, note the agreeing specialists" [label="yes"];
  "Reported by multiple specialists?" -> "AAA criterion?" [label="no"];
  "Merge duplicates, note the agreeing specialists" -> "AAA criterion?";
  "AAA criterion?" -> "List under Minor Issues & AAA Recommendations, prefix [AAA]" [label="yes — a recommendation, not a failure"];
  "AAA criterion?" -> "Place under its severity section" [label="no"];

  "List under Minor Issues & AAA Recommendations, prefix [AAA]" -> "Write report to paad/a11y-reviews/a11y-<timestamp>.md";
  "Place under its severity section" -> "Write report to paad/a11y-reviews/a11y-<timestamp>.md";
  "DROP the finding" -> "Write report to paad/a11y-reviews/a11y-<timestamp>.md" [label="counted under Filtered out"];
  "Write report to paad/a11y-reviews/a11y-<timestamp>.md" -> "Report location, counts by severity, Quick Wins guidance";
  "Report location, counts by severity, Quick Wins guidance" -> "STOP: report is the deliverable — do NOT auto-fix";
}

When NOT to Use This Skill

  • The user needs a legal conformance statement (VPAT, EN 301 549 attestation) — this produces an engineering audit, not a certified accessibility conformance report. Say so rather than letting a report be mistaken for one.

Arguments

/agentic-a11y accepts optional $ARGUMENTS:

  • /agentic-a11y — audit all user-facing code in the repository
  • /agentic-a11y src/components/ — scope the audit to a specific directory
  • /agentic-a11y src/components/Modal.tsx — audit a specific file

When a path is provided, only audit files within that scope. Still detect platform and run all specialists, but limit the file manifest accordingly.

Pre-flight Checks

  1. Context window: If conversation has substantive history beyond invoking this skill, tell the user: "This audit consumes significant context. Start a fresh session with /agentic-a11y to avoid context rot." Stop and wait.
  2. User-facing code: Scan for any of the following. If none found, tell the user: "No user-facing code detected in this repository." Stop.
PlatformFile indicators
Web.html, .jsx, .tsx, .vue, .svelte, .ejs, .hbs, .blade.php, .erb, .jinja, .twig, .css, .scss, .less, plus JS/TS with DOM manipulation
iOS (native).swift (SwiftUI views), .m/.h (UIKit), .storyboard, .xib
Android (native).kt/.java (Compose or View classes), res/layout/*.xml
React Native.jsx/.tsx with react-native imports
Flutter.dart files with package:flutter imports
DesktopElectron (web stack), Qt (.cpp/.qml), WPF/WinForms (.xaml/.cs), macOS AppKit/SwiftUI, GTK
CLIAny code producing terminal output or accepting terminal input (look for stdout/stderr writes, readline, prompt libraries, curses/ncurses, argument parsers)
GameUnity (.cs scripts), Unreal (C++/Blueprints), Godot (.gd/.tscn), custom engines with rendering/input systems

Phase 1: Reconnaissance

Run these steps and collect results:

1. Platform detection

Classify the project into one or more platforms from the table above. A project may span multiple platforms (e.g., a web app with a CLI tool, or a React Native app with web support). Record all detected platforms — specialists will receive this classification.

2. Tech stack identification

Per detected platform:

  • Web: Frameworks (React, Vue, Angular, Svelte, Next.js, etc.), CSS approach (Tailwind, CSS Modules, styled-components, etc.), component libraries (MUI, Radix, Headless UI, Bootstrap — note built-in a11y support)
  • iOS: SwiftUI vs UIKit vs mixed, any a11y wrapper libraries
  • Android: Jetpack Compose vs View system vs mixed, any a11y libraries
  • React Native: version, any a11y libraries (e.g., react-native-a11y)
  • Flutter: version, any a11y packages
  • Desktop: framework and toolkit
  • CLI: argument parser, output formatting library, terminal UI library (if any)
  • Game: engine, UI system (in-engine UI, HTML overlay, custom)

3. Inventory user-facing code

Collect all files that produce user-facing output or handle user interaction, grouped by platform.

4. Check for existing a11y tooling

  • Web: eslint-plugin-jsx-a11y, eslint-plugin-vuejs-accessibility, axe-core, pa11y, Lighthouse configs
  • iOS: Accessibility Inspector usage, XCTest accessibility tests
  • Android: Accessibility Scanner, Espresso accessibility checks, AccessibilityChecks.enable()
  • React Native: @testing-library/react-native accessibility queries
  • Flutter: SemanticsDebugger, accessibility-related widget tests
  • CLI: structured output tests, --no-color support tests
  • Game: accessibility options menu, remapping tests
  • CI: any automated a11y checks in CI pipeline
  • Note what's present — specialists should not re-flag issues that existing tooling already catches, unless the tooling is misconfigured or findings are suppressed

5. Scan for steering files

CLAUDE.md, AGENTS.md, any a11y-specific documentation or guidelines.

6. Estimate scope size

  • Small: <20 user-facing files
  • Medium: 20-100 user-facing files
  • Large: 100+ user-facing files

7. Build manifest

Files to audit, grouped for specialists, annotated with detected platform(s).

Steering file caveat: Include in every agent prompt: "Steering files (CLAUDE.md, etc.) describe conventions but may be stale. If you find a contradiction between steering files and actual code, flag it as a finding."

Phase 2: Specialist Audit (Parallel)

Dispatch these agents simultaneously using the Agent tool with subagent_type: paad:paad-analyst. Each receives: the file manifest, detected platform(s), steering file contents, existing a11y tooling notes, and their specialist focus.

Core specialists (always dispatched)

AgentFocusWho it helps
Screen Reader & Assistive TechProgrammatic exposure of UI semantics so assistive technologies can convey structure, content, and state to usersBlind and low-vision users using screen readers (VoiceOver, TalkBack, NVDA, JAWS, Orca)
Visual & ColorSufficient contrast, independence from color alone, support for magnification/text scaling, visible focus/selection indicatorsLow-vision users, colorblind users
Keyboard & MotorComplete operability without fine motor control — keyboard, switch, sip-and-puff, eye tracking, voice control — with adequate target sizes and no trapsMotor-impaired users, switch access users, sip-and-puff users, voice control users
Cognitive & LearningConsistent, predictable interfaces with clear feedback, error recovery, plain language, and no unnecessary cognitive loadUsers with cognitive disabilities, learning disabilities, attention disorders, memory impairments
Multimedia & TemporalAlternatives for audio/visual content, safe motion/animation, adequate time, no seizure triggersDeaf/hard-of-hearing users, vestibular disorders, photosensitive epilepsy, users who need more time

Conditional specialist

Dispatch using the Agent tool with subagent_type: paad:paad-analyst, exactly as for the core specialists, when the platform has framework-specific a11y pitfalls (web frameworks, SwiftUI, Compose, Flutter, React Native, game engines):

AgentFocusInput
Platform-Specific PatternsFramework/platform-specific a11y pitfalls, misuse of platform a11y APIs, navigation/routing a11y, dynamic content patternsFile manifest + platform/framework detection results

Agent prompt template

Each specialist agent prompt must include:

  • The list of files to audit (from their manifest group)
  • Contents of files in their audit scope
  • The detected platform(s)
  • Steering file contents with the staleness caveat
  • Existing a11y tooling notes
  • Instruction: "You are an accessibility specialist focused on [FOCUS AREA]. The detected platform(s) for this project: [PLATFORMS]. Your goal is to find accessibility barriers that affect [USER GROUP]. For each finding report: file:line, what's wrong, which accessibility criterion it violates (WCAG 2.2 criterion where applicable, or platform-specific guideline), the conformance level (A/AA/AAA), who is affected and how, a concrete code-level fix, and your confidence (0-100). Only report findings with confidence >= 60. Do not modify any file in the repository. You may run read-only commands (existing tests, linters, type checkers) unchanged — their caches, coverage files, and build output are fine. If confirming a finding would require changing code, do not — cap that finding's confidence at 79 and state what would confirm it."

Platform-specific checks per specialist

Include the relevant platform section(s) in each specialist's prompt based on detected platform(s).

Screen Reader & Assistive Tech

Web: (1) Correct ARIA roles, states, and properties on custom components; (2) semantic HTML (headings, landmarks, lists, tables) over generic div/span; (3) heading hierarchy without skipped levels; (4) meaningful alt text (not filenames or "image"); (5) programmatically associated form labels; (6) aria-live regions for dynamic content; (7) link/button purpose clear from text or accessible name; (8) status messages via role="status" or aria-live.

iOS: (1) accessibilityLabel set on all interactive and meaningful elements; (2) accessibilityTraits / SwiftUI .accessibilityAddTraits() correctly applied (.button, .header, .image, etc.); (3) accessibilityHint for non-obvious actions; (4) isAccessibilityElement grouping — containers group related info, decorative elements excluded; (5) accessibilityValue for sliders/progress; (6) UIAccessibility.post(.screenChanged, ...) and .layoutChanged notifications for dynamic updates; (7) custom actions via accessibilityCustomActions; (8) SwiftUI: .accessibilityElement(children: .combine) for logical grouping.

Android: (1) contentDescription on all interactive and meaningful elements; (2) importantForAccessibility set correctly — decorative elements marked no; (3) labelFor connecting labels to inputs; (4) accessibilityLiveRegion for dynamic content; (5) accessibilityHeading on section headers; (6) Compose: semantics { } block with appropriate properties, contentDescription, heading(), stateDescription; (7) custom AccessibilityNodeInfo actions where needed; (8) ViewCompat.setAccessibilityDelegate for custom views.

React Native: (1) accessibilityLabel on all interactive elements; (2) accessibilityRole set correctly (button, header, link, image, etc.); (3) accessibilityState for toggles, disabled, expanded states; (4) accessibilityHint for non-obvious actions; (5) accessibilityLiveRegion for dynamic updates; (6) accessibilityElementsHidden for decorative content; (7) AccessibilityInfo.announceForAccessibility() for dynamic state changes.

Flutter: (1) Semantics widget wrapping meaningful UI with label, button, header, image properties; (2) excludeSemantics: true on decorative elements; (3) MergeSemantics for logically grouped content; (4) SemanticsService.announce() for dynamic updates; (5) tooltip properties on IconButton and similar; (6) semanticsLabel on Text where displayed text differs from meaning.

CLI: (1) Structured, parseable output (not just visual formatting with boxes/lines); (2) information not conveyed solely by position/layout — screen readers linearize output; (3) progress indication via text updates, not just spinners or progress bars that rely on cursor repositioning; (4) error messages written to stderr with clear text (not just color/emoji).

Game: (1) UI elements have text alternatives available for screen reader narration mode; (2) menu items narrated with name, type, and state; (3) game state changes announced; (4) narration option in settings if not always-on.

Visual & Color

Web: Contrast ratios — AA: 4.5:1 normal text, 3:1 large text (18pt+/14pt+ bold), 3:1 UI components and graphics. AAA: 7:1/4.5:1. Check CSS custom properties and theme values. Flag color-only meaning (error states, status indicators, required fields, links distinguished only by color). Reflow at 320px width. Text spacing override support. prefers-contrast media query support.

iOS: (1) Dynamic Type support (UIFontMetrics, SwiftUI .dynamicTypeSize), test with all type sizes including accessibility sizes; (2) Bold Text support (UIAccessibility.isBoldTextEnabled); (3) Increase Contrast (UIAccessibility.isDarkerSystemColorsEnabled); (4) Reduce Transparency support; (5) sufficient contrast ratios in custom themes (same ratios as web); (6) color-only information has shape/icon/text alternatives; (7) SF Symbols accessibility variants.

Android: (1) sp units for text (scales with user preference); (2) test at 200% font scale; (3) High Contrast Text setting support; (4) sufficient contrast in custom themes; (5) color-only meaning has alternatives; (6) Magnification gesture compatibility (no content hidden at 200%+ zoom); (7) custom views render correctly with font scaling.

React Native: (1) Font scaling support — not disabled via allowFontScaling={false} unless justified; (2) layout accommodates scaled text without overflow/truncation; (3) contrast ratios on all custom-themed elements; (4) color-only meaning has alternatives.

Flutter: (1) MediaQuery.textScaleFactorOf(context) respected — UI tested at 2.0 scale; (2) contrast ratios met in custom ThemeData; (3) color-only meaning has alternatives; (4) MediaQuery.boldTextOf(context) support; (5) MediaQuery.highContrastOf(context) support.

CLI: (1) --no-color flag or NO_COLOR env var support; (2) information not conveyed by color alone — use labels, prefixes, symbols alongside color (e.g., [ERROR] not just red text); (3) supports TERM detection for capability; (4) works in high-contrast terminal themes.

Game: (1) Colorblind mode(s) — at minimum deuteranopia (red-green), ideally also protanopia and tritanopia; (2) UI element outlines/patterns supplement color; (3) font size options or UI scaling; (4) high contrast UI option; (5) brightness/gamma controls; (6) important game elements distinguishable by shape, not just color.

Keyboard & Motor

Web: (1) Every interactive element reachable and activatable via keyboard; (2) no keyboard traps (focus can escape every modal, dropdown, overlay); (3) logical focus order matching visual layout; (4) visible focus indicators (not suppressed by outline: none without replacement); (5) skip navigation links; (6) custom widgets follow WAI-ARIA Authoring Practices keyboard patterns; (7) click targets at least 24x24 CSS px (AA), recommend 44x44 (AAA); (8) drag-and-drop has click/keyboard alternative; (9) single-character shortcuts remappable or only active on focus; (10) pointer-events, user-select not disabling expected interactions.

iOS: (1) Full Keyboard Access support — all actions reachable via external keyboard; (2) Switch Control compatibility — all interactive elements in accessibility tree with correct order; (3) AssistiveTouch custom gesture alternatives for complex gestures; (4) minimum 44x44pt tap targets (Apple HIG); (5) no gesture-only actions without alternatives (e.g., swipe-to-delete must have edit button); (6) custom gesture recognizers don't block Switch Control; (7) accessibilityActivationPoint set for non-standard hit areas.

Android: (1) Full keyboard navigation — android:focusable, logical nextFocusDown/Up/Left/Right; (2) Switch Access compatibility — all interactive elements focusable with adequate ordering; (3) minimum 48x48dp touch targets (Material Design); (4) no gesture-only actions without alternatives; (5) android:importantForAccessibility not hiding interactive elements; (6) custom views implement onKeyDown/onKeyUp for keyboard users; (7) TalkBack gesture alternatives for complex interactions.

React Native: (1) accessible={true} on all interactive elements; (2) accessibilityActions for custom actions; (3) onMagicTap, onEscape handlers where appropriate (iOS); (4) minimum touch target sizes (48x48dp Android / 44x44pt iOS); (5) gesture-based interactions have tap alternatives.

Flutter: (1) All interactive widgets have Semantics with tap/long press actions; (2) minimum touch targets via MaterialTapTargetSize.padded; (3) FocusNode and FocusTraversalGroup for logical keyboard order; (4) RawKeyboardListener/KeyboardListener for keyboard shortcuts; (5) no IgnorePointer/AbsorbPointer hiding accessible interactions; (6) custom GestureDetector actions have keyboard alternatives.

CLI: (1) Keyboard-only by nature, but check: interactive prompts (e.g., fuzzy finders, multi-select) navigable with arrow keys and enter; (2) Ctrl-C always exits; (3) no mouse-only interactions in TUI; (4) tab completion where appropriate; (5) long-running operations cancellable via keyboard.

Game: (1) Fully remappable controls; (2) multiple input device support (keyboard, mouse, controller, touch); (3) one-handed mode or alternative layouts; (4) no quick-time events without alternatives or adjustable timing; (5) auto-aim/aim assist option; (6) adjustable input sensitivity/dead zones; (7) hold-vs-toggle options for sustained inputs; (8) copilot/co-pilot mode if multiplayer.

Cognitive & Learning

All platforms: (1) Consistent navigation patterns across screens/pages; (2) consistent identification of common elements; (3) clear error messages identifying the problem and suggesting a fix; (4) labels and instructions on all form inputs; (5) predictable behavior — no unexpected context changes on focus or input; (6) adequate time — adjustable/extendable timeouts, warnings before expiry; (7) help in a consistent, findable location; (8) no unnecessary re-entry of previously provided information; (9) accessible authentication — no cognitive function tests (CAPTCHAs) without alternatives.

Web additionally: (1) lang attribute on <html> and lang attributes on content in other languages; (2) multiple ways to find pages (nav, search, sitemap); (3) breadcrumbs or location indicator.

iOS/Android additionally: (1) Back navigation always works predictably; (2) undo support for destructive actions; (3) confirmation dialogs for irreversible operations.

CLI additionally: (1) --help with clear, complete documentation; (2) confirmation prompts for destructive commands (with --yes/-y to skip); (3) meaningful exit codes; (4) consistent flag naming conventions (e.g., --verbose not -v in one command and --debug in another).

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
112
Forks
10
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
agentic-a11y
Source
github.com/ovid/paad