agentleFS
greglas75greglas75/zuvo/skills/a11y-audit/SKILL.md

a11y-audit

Skill7 starsChanged 28 days agoMITView on GitHub

Dedicated WCAG 2.2 AA/AAA accessibility audit across 10 dimensions (A1-A10) covering semantic HTML, keyboard navigation, ARIA patterns, color contrast, forms, images/media, responsive/zoom, motion/animation, reading/content, and legal compliance. Goes far beyond surface-level design-review checks with deep compliance-focused analysis, WCAG criterion mapping, and legal risk assessment (ADA Title II, EAA, Section 508). Critical gates on keyboard (A2) and contrast (A4). Flags: [path] | full | --live-url <url> | --quick | --fix | --standard AA|AAA | --legal ada|eaa|508.

34 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use perf-audit, design-tokens and 3 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • WhatIfWeDigDeeperSkill

    perf-audit

    Profile and optimize React application performance

    Also in 4 projects that use this

  • ilikescienceSkill

    design-tokens

    Expert in design tokens using the DTCG specification. Use this skill when users ask about design tokens, DTCG format, token validation, formatting, transformation, color spaces (sRGB, Display P3, OKLCH), references and aliasing, resolvers, theming with modifiers/contexts, multi-platform design systems, accessibility, or working with tools like jq, jsonata, and terrazzo. Helps with token file creation, resolver configuration, structure, naming conventions, and best practices.

    Also in 4 projects that use this

  • lbednerSkill

    i18n

    Use when a code or template change introduces a new translation message key, in either the framework CLI (aegis/i18n/locales/) or a generated project's CLI (the app/i18n/locales/ template tree). Covers adding the real English string, stubbing the same key into every other locale for parity, and the separate translation PR that later replaces placeholders with reviewed native text.

    Also in 3 projects that use this

  • AnthropicSkill

    design-system

    Audit, document, or extend your design system. Use when checking for naming inconsistencies or hardcoded values across components, writing documentation for a component's variants, states, and accessibility notes, or designing a new pattern that fits the existing system.

    Also in 3 projects that use this

  • HashiCorpSkill

    changelog

    Add a `.changelog/<PR_NUMBER>.txt` entry for a GitHub Pull Request, commit, and push.

    Also in 3 projects that use this

The file

Show its rules and text

We split this skill into the rules it gives an agent

22 rules. 0 are common, 9 are distinctive, and 13 are very specific to this project.

  • 0

    Common

    Most of the 27 edited versions we read keep these.

  • 9

    Distinctive

    This author's own choices. Worth a look.

  • 13

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When to use: Before public launches, when targeting WCAG compliance, after ADA/EAA legal requirements surface, periodic accessibility …

    line 55
  2. Distinctive:

    Read these files before any work begins.

    line 83
  3. Very specific:

    Read ../../shared/includes/env-compat.md for agent dispatch patterns, path resolution, and progress tracking across all supported platforms.

    line 105
  4. Very specific:

    Use the deterministic preload helper FIRST: Run ~/.zuvo/compute-preload a11y-audit "$PWD".

    line 128
  5. Very specific:

    Read ../../shared/includes/codesift-setup.md for the full initialization sequence.

    line 134
  6. Very specific:

    Check package.json dependencies, config files (next.config.*, astro.config.*, svelte.config.*, angular.json)

    line 272
  7. Distinctive:

    Run grep/CodeSift scans across the codebase for:

    line 307
  8. Very specific:

    If eslint-plugin-jsx-a11y is detected:

    line 330
  9. Distinctive:

    If not available: skip, rely on manual scan.

    line 336
  10. Very specific:

    If mcp-accessibility-scanner is available:

    line 373
  11. Very specific:

    If chrome-devtools MCP is available but not accessibility-scanner:

    line 378
  12. Very specific:

    Run evaluate_script with axe-core injection

    line 380
  13. Very specific:

    If --dry-run flag is set: report all fixes without applying.

    line 451
  14. Very specific:

    If --fix flag is set:

    line 453
  15. Distinctive:

    Run verification: check that fixes don't break existing tests

    line 456
  16. Distinctive:

    If tests fail after a fix: revert that specific fix, keep the tag for manual rollback

    line 457
  17. Distinctive:

    Before printing the final output block, verify every item.

    line 602
  18. Distinctive:

    After completing the audit, print:

    line 616
  19. Very specific:

    If gate_status = FAIL → VERDICT = INCOMPLETE.

    line 650
  20. Very specific:

    Follow the retrospective protocol from retrospective.md.

    line 659
  21. Distinctive:

    If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

    line 661
  22. Very specific:

    After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

    line 663

“Common” is measured: kept by at least 6 in 10 of the 27 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

zuvo:a11y-audit — WCAG 2.2 Accessibility Audit

Deep, compliance-focused accessibility audit across 10 weighted dimensions with WCAG 2.2 criterion mapping, legal risk assessment, and actionable fix generation. Every finding maps to a specific WCAG success criterion and severity level.

When to use: Before public launches, when targeting WCAG compliance, after ADA/EAA legal requirements surface, periodic accessibility health checks, when onboarding a codebase that must meet compliance standards, after adding interactive components or forms. Out of scope: Surface-level design consistency (zuvo:design-review), visual design quality (zuvo:ui-design-team), code quality (zuvo:code-audit), penetration testing (zuvo:pentest).

Argument Parsing

Parse $ARGUMENTS for these flags:

ArgumentEffect
[path]Audit a specific directory or component
fullAudit the entire project
--live-url <url>Enable browser-based testing (axe-core via MCP)
--quickCritical gates only (A2 Keyboard, A4 Contrast)
--fixGenerate fix code for all findings
--standard AA|AAACompliance level (default: AA)
--legal ada|eaa|508Focus on a specific legal standard
--max-files [N]Cap audit to N files (default: 40)
--persist-backlogRecord CRITICAL/HIGH findings via backlog-add (also done whenever a CRITICAL finding exists)
ModeScopePhasesBrowser
[path]Directory/component0-5No
fullEntire project0-5No
--live-urlProject + URL0-5 incl. Phase 2 browserYes
--quickProject0, 1 (A2+A4 only), 5No

Mandatory File Loading

Read these files before any work begins. Print the checklist with status.

Stage 1 -- Before Phase 0 (STOP if any missing):

CORE FILES LOADED:
  1. ../../shared/includes/codesift-setup.md  -- [READ | MISSING -> STOP]
  2. ../../shared/includes/env-compat.md      -- [READ | MISSING -> STOP]

Stage 2 -- Before Phase 5 (report writing):

  3. ../../shared/includes/run-logger.md      -- [READ | MISSING -> STOP]
  4. ../../shared/includes/retrospective.md      -- [READ | MISSING -> STOP]
  5. ../../shared/includes/backlog-protocol.md -- [READ | MISSING -> degraded]

Stage 2 deferred to save upfront context.

Environment Compatibility

Read ../../shared/includes/env-compat.md for agent dispatch patterns, path resolution, and progress tracking across all supported platforms.

MANDATORY TOOL CALLS — A11y Audit Validity Gate

INVALID if any tool below is skipped. "DEFERRED", "N/A" NOT valid reasons.

ToolTriggerSkip allowed?
get_file_treeAlwaysNO
search_textAlwaysNO — aria-*, role=, alt=, tabindex, lang attrs
search_symbolsAlwaysNO — interactive component discovery
search_patternsAlwaysNO — WCAG anti-patterns (missing alt, nested interactive)
audit_scanAlwaysNO — compound check
React tools (analyze_hooks, trace_component_tree)React detectedNO when React

Forbidden: same as above (skipped/N/A/codesift unavailable when deferred — REJECTED).

POSTAMBLE: report on disk → retro appended → ~/.zuvo/append-runlog exit 0. Every A-dim finding needs path/to/file.ext:LINE (verify-audit gate).

Mandatory-tools-acknowledgment: I will run get_file_tree + search_text + search_symbols + search_patterns + audit_scan + React tools (when React) for this a11y audit. Every A-dim finding will cite a `path/to/file.ext:LINE` resolving in the current tree.

Use the deterministic preload helper FIRST. Run ~/.zuvo/compute-preload a11y-audit "$PWD". Math gate enforced.


CodeSift Integration

Read ../../shared/includes/codesift-setup.md for the full initialization sequence.

a11y-audit CodeSift usage:

  • search_text(repo, "aria-|role=", regex=true, file_pattern="*.tsx") -- ARIA attribute scan
  • search_text(repo, "<h[1-6]", regex=true, file_pattern="*.tsx") -- heading inventory
  • search_text(repo, "tabindex\|tabIndex", regex=true) -- tabindex usage
  • search_text(repo, ":focus-visible\|:focus", regex=true, file_pattern="*.css") -- focus style scan
  • search_text(repo, "prefers-reduced-motion", file_pattern="*.css") -- motion media query
  • search_text(repo, "alt=", file_pattern="*.tsx") -- alt text coverage
  • search_symbols(repo, "useReducedMotion|usePrefersReducedMotion", include_source=true) -- motion hook usage

Degraded Mode (CodeSift unavailable)

CodeSift toolFallbackLost capability
search_text (ARIA)Grep for ARIA attributesSame coverage, more tokens
search_symbols (hooks)Grep for hook namesLess precise matches
get_file_treefind commandSlower, no symbol counts
get_file_outlineRead each fileMore tokens consumed

Dimensions (A1-A10)

A1: Semantic HTML (weight 10)

CheckWCAGDetection
Heading hierarchy (h1-h6 in order, no skips)1.3.1Scan for <h1>-<h6> ordering per page/component
Landmark regions (nav, main, aside, footer, header)1.3.1Grep for landmark elements or ARIA landmark roles
Lists used for list content (not divs)1.3.1Pattern: repeated sibling divs that should be <ul>/<li>
Tables with proper thead/th/scope1.3.1Grep for <table> without <th> or missing scope
Buttons vs links (button for actions, a for navigation)4.1.2<a> with onClick and no href, <div> with click handlers

A2: Keyboard Navigation (weight 12, CRITICAL GATE)

CheckWCAGDetection
All interactive elements focusable2.1.1<div onClick> without tabIndex or role="button"
Tab order matches visual order (no positive tabindex)2.4.3tabindex values > 0
Focus visible on all interactive elements2.4.7:focus-visible or :focus styles present for interactive elements
No keyboard traps2.1.2Modal/dialog without escape handler, custom widgets without blur path
Skip navigation link present2.4.1First focusable element links to #main or #content
Custom component keyboard handlers2.1.1Custom interactive elements missing onKeyDown/onKeyUp for Enter, Space, Escape, Arrow keys
Modal/dialog focus management2.4.3Focus trapped inside modal, focus returns to trigger on close

A3: ARIA Patterns (weight 10)

CheckWCAGDetection
ARIA roles match component behavior4.1.2Role attribute vs actual element behavior
aria-label/aria-labelledby on elements without visible text4.1.2Icon buttons, image-only links without label
aria-expanded on toggleable elements4.1.2Dropdowns, accordions missing aria-expanded
aria-live regions for dynamic content4.1.3Toast, notification, status updates without aria-live
aria-hidden on decorative elements4.1.2Decorative icons/images without aria-hidden="true"
No redundant ARIA4.1.2role="button" on <button>, role="link" on <a>
aria-describedby for form field help text1.3.1Help text near inputs without association

A4: Color & Contrast (weight 10, CRITICAL GATE)

CheckWCAGDetection
Text contrast >= 4.5:1 (normal), >= 3:1 (large)1.4.3Extract color values from CSS/tokens, compute ratios
UI component contrast >= 3:11.4.11Border, icon, form control colors vs background
Information not conveyed by color alone1.4.1Status indicators, error states using only color
Focus indicator contrast >= 3:11.4.11Focus ring color vs surrounding background
Light and dark theme coverage1.4.3Both themes checked if prefers-color-scheme or theme toggle exists

A5: Forms & Inputs (weight 10)

CheckWCAGDetection
Every input has associated label1.3.1, 3.3.2<input> without <label>, aria-label, or aria-labelledby
Error messages linked to fields3.3.1Error elements without aria-describedby or aria-errormessage
Required fields marked3.3.2Missing aria-required="true" and no visual indicator
Autocomplete attributes on common fields1.3.5Name, email, phone, address inputs without autocomplete
Form validation errors announced4.1.3Error summary not in aria-live region
Related fields grouped1.3.1Radio groups, address fields without <fieldset>/<legend>

A6: Images & Media (weight 8)

CheckWCAGDetection
Informative images have alt text1.1.1<img> without alt, or alt="image" / alt="photo"
Decorative images have alt="" or aria-hidden1.1.1Decorative images with meaningful alt
Complex images have long description1.1.1Charts, diagrams without aria-describedby or <figcaption>
Video has captions/subtitles1.2.2<video> without <track kind="captions">
Audio has transcript1.2.1<audio> without transcript link
SVG has title or aria-label1.1.1, 4.1.2<svg> without <title> or aria-label
No auto-playing media1.4.2autoplay attribute without pause control

A7: Responsive & Zoom (weight 6)

CheckWCAGDetection
Content reflows at 320px width1.4.10Horizontal scroll triggers, fixed-width containers
Text resizable to 200%1.4.4Font sizes in px instead of rem/em
Touch targets minimum 44x44px2.5.8Small click/tap targets (links, buttons, icons)
No content hidden at zoom1.4.10overflow: hidden on containers with text
Viewport no disable scaling1.4.4maximum-scale=1 or user-scalable=no in viewport meta

A8: Motion & Animation (weight 5)

CheckWCAGDetection
prefers-reduced-motion respected2.3.3CSS @media (prefers-reduced-motion) present
No content flashes > 3 times/sec2.3.1Animation durations < 333ms with repeating patterns
Animations can be paused/stopped2.2.2Auto-playing animations without pause control
Carousels have pause control2.2.2Auto-advancing carousels without pause button
Page transitions respect reduced motion2.3.3Route transitions without motion preference check

A9: Reading & Content (weight 5)

CheckWCAGDetection
html lang attribute set3.1.1<html> without lang attribute
Language changes marked3.1.2Foreign-language content without lang attribute
Link text is descriptive2.4.4"click here", "read more", "learn more" without context
Consistent navigation3.2.3Nav component differs across pages
Page titles descriptive and unique2.4.2Missing <title>, duplicate titles, generic titles

A10: Legal Compliance Status (NOT scored — separate legal risk section)

A10 is a qualitative legal risk assessment, not a scored dimension. It does NOT contribute to the numerical score (to avoid double-counting A1-A9 results). It appears as a standalone section in the report.

CheckStandardDetection
ADA Title II compliance (deadline: 2026-04-24)ADAMap A1-A9 failures to ADA requirements. If audit date < deadline: flag as APPROACHING. If audit date >= deadline: flag as POST-DEADLINE (compliance now mandatory).
European Accessibility Act complianceEAAMap failures to EAA requirements (if EU-facing)
Section 508 compliance508Map failures to Section 508 (if government)
VPAT readinessVPATAssess documentation completeness for VPAT generation
Accessibility statement presentAllCheck for /accessibility page or statement in footer

Phase 0: Detection

  1. Detect framework: React, Next.js, Vue, Nuxt, Svelte, SvelteKit, Astro, Angular, plain HTML
    • Check package.json dependencies, config files (next.config.*, astro.config.*, svelte.config.*, angular.json)
  2. Detect component library: MUI, Chakra, Radix, Headless UI, shadcn, Mantine, Ant Design, none
    • Check package.json dependencies
  3. Detect existing a11y tooling:
    • eslint-plugin-jsx-a11y in devDependencies
    • axe-core or @axe-core/* in devDependencies
    • pa11y in devDependencies or global
    • jest-axe or vitest-axe in devDependencies
    • Storybook a11y addon (@storybook/addon-a11y)
  4. Detect existing a11y config:
    • .axerc or axe.config.js
    • .pa11y or .pa11yci
    • eslintrc with jsx-a11y rules
  5. Estimate scope: Count pages/components for workload sizing

Output:

A11Y DETECTION
  Framework:   [name]
  Components:  [library or "custom"]
  A11y tools:  [list or "none detected"]
  A11y config: [list or "none"]
  Scope:       [N pages, N components]
  Standard:    WCAG 2.2 [AA|AAA]
  Legal focus:  [ADA Title II | EAA | Section 508 | N/A]

Phase 1: Static Code Analysis (A1-A9)

Scan templates, JSX/TSX, CSS, and config files against all dimension checks.

1.1 Batch Scans

Run grep/CodeSift scans across the codebase for:

ScanTargetDimension
Heading inventory<h1>-<h6> elements per fileA1
Landmark elements<nav>, <main>, <aside>, <header>, <footer>A1
ARIA attributesaria-* attribute usage and coverageA3
Focus styles:focus-visible, :focus, outline: in CSSA2
Tabindex usagetabindex/tabIndex valuesA2
Skip nav linkFirst focusable element patternA2
Keyboard handlersonKeyDown, onKeyUp, onKeyPress on custom elementsA2
Color valuesHardcoded hex/rgb in CSS, contrast-relevant variablesA4
Alt textalt= attribute presence and qualityA6
Form labels<label>, aria-label, aria-labelledby on inputsA5
Autocompleteautocomplete on common input typesA5
Viewport metaviewport meta tag contentA7
Reduced motionprefers-reduced-motion media queryA8
Lang attribute<html lang= in root templatesA9
Link text"click here", "read more", "learn more" patternsA9
SVG accessibility<title> or aria-label on SVGsA6

1.2 eslint-plugin-jsx-a11y Integration

If eslint-plugin-jsx-a11y is detected:

  1. Grep the ESLint config for disabled jsx-a11y/* rules — note each as an intentional exception
  2. Run with project config: npx eslint --ext .jsx,.tsx [scope] — captures what the project considers violations
  3. Run baseline scan: npx eslint --no-eslintrc --plugin jsx-a11y --rule '{...}' [scope] — captures ALL violations including intentionally suppressed ones
  4. Diff the two runs — suppressions found in config but not in baseline are intentional exceptions. Report them as [SUPPRESSED] findings (user decided to allow this) vs [ACTIVE] findings (violations the project config also flags)

If not available: skip, rely on manual scan.

1.3 Per-Component Scoring

For each page/component in scope, evaluate A1-A9 checks:

### [file path]
Component type: [PAGE | FEATURE | SHARED]
| Dim | Score | Max | Evidence |
|-----|-------|-----|----------|
| A1  | [N]   | 10  | [summary] |
| A2  | [N]   | 12  | [summary] |
| A3  | [N]   | 10  | [summary] |
| A4  | [N]   | 10  | [summary] |
| A5  | [N]   | 10  | [summary] |
| A6  | [N]   | 8   | [summary] |
| A7  | [N]   | 6   | [summary] |
| A8  | [N]   | 5   | [summary] |
| A9  | [N]   | 5   | [summary] |
Critical gates: A2=[N]/12 A4=[N]/10 -- [PASS/FAIL]

Scoring per dimension: Each check within a dimension scores proportionally. Example: A1 has 5 checks, each worth 2 points (total 10). A check scores 0 (fail), 1 (partial), or full points (pass).

Dispatch follows ../../shared/includes/execution-policy.md through env-compat. Reuse existing authorization within that policy; session restrictions take precedence. Run each required gate and report its actual independence or an unmet requirement.

If >10 components: Split into batches of 5. Dispatch background agents where env-compat supports parallel dispatch.


Phase 2: Automated Testing

2.1 Browser-Based (if --live-url and browser MCP available)

If mcp-accessibility-scanner is available:

  • scan_page(url) per route for axe-core violations
  • scan_page_matrix(url, variants=["mobile", "forced-colors", "reduced-motion", "zoom-200%"]) for variant testing
  • audit_keyboard(url) for tab order, focus visibility, keyboard traps

If chrome-devtools MCP is available but not accessibility-scanner:

  • Navigate to pages via navigate_page
  • Run evaluate_script with axe-core injection
  • Take screenshots at multiple viewport sizes

axe-core results override static scan findings: Where automated tools provide definitive results, they take precedence over grep-based analysis.

2.2 pa11y Integration (if available)

If pa11y is available:

npx pa11y [url] --reporter json --standard WCAG2AA

Parse JSON output, map violations to A1-A10 dimensions.

2.3 Automated Coverage Note

Automated tools catch approximately 30-57% of WCAG issues. The following CANNOT be caught by automated tools and require manual verification:

  • Meaningful alt text quality (automated can detect presence, not quality)
  • Keyboard trap detection in complex widgets
  • Logical reading order
  • Content comprehension at different zoom levels
  • Whether color alone conveys information (context-dependent)
  • Focus management correctness in SPAs
  • Screen reader announcement quality

Phase 3: Manual Checklist Verification

For each dimension, verify against WCAG 2.2 success criteria:

  1. Map every finding to a specific WCAG criterion (e.g., "1.1.1 Non-text Content", "2.1.1 Keyboard")
  2. Classify each check as:
    • PASS -- criterion satisfied with evidence
    • FAIL -- criterion violated with evidence
    • CANNOT DETERMINE -- requires manual verification (e.g., screen reader testing, cognitive assessment)
  3. For CANNOT DETERMINE items, describe what manual test is needed

WCAG Level mapping:

  • Level A (minimum): 1.1.1, 1.2.1, 1.3.1, 1.4.1, 2.1.1, 2.1.2, 2.2.2, 2.3.1, 2.4.1, 2.4.2, 2.4.3, 2.4.4, 3.1.1, 3.2.1, 3.3.1, 3.3.2, 4.1.2
  • Level AA (standard target): Level A + 1.3.5, 1.4.3, 1.4.4, 1.4.10, 1.4.11, 2.4.7, 3.1.2, 3.2.3, 3.3.3, 4.1.3
  • Level AAA (if --standard AAA): Level AA + 1.4.6 (7:1 contrast), 2.3.3, 2.4.9, 2.5.8, 3.1.5, 3.1.6

Phase 4: Fix Generation (if --fix or findings exist)

For each finding, generate a specific code fix:

### A11Y-[NNN]: [Title]
Dimension: A[N]
WCAG: [criterion number] [criterion name]
Severity: CRITICAL | HIGH | MEDIUM
Level: A | AA | AAA
File: [path:line]
Impact: [who is affected and how]

Before:
  [code snippet showing the violation]

After:
  [code snippet with the fix applied]

Notes: [implementation considerations]

Prioritization order:

  1. Legal risk (CRITICAL findings in dimensions relevant to --legal standard)
  2. User impact (keyboard/screen reader blockers > visual issues > enhancements)
  3. Effort (quick wins first within same priority tier)

If --dry-run flag is set: report all fixes without applying. Show before/after code for each fix.

If --fix flag is set:

  1. Create rollback tag: git tag a11y-fix-YYYY-MM-DD before applying any changes
  2. Apply all CRITICAL and HIGH fixes automatically. MEDIUM fixes are reported but not auto-applied.
  3. Run verification: check that fixes don't break existing tests
  4. If tests fail after a fix: revert that specific fix, keep the tag for manual rollback

Scope guard: Fixes touch only accessibility attributes, ARIA properties, semantic elements, CSS focus/contrast styles, and meta tags. Fixes do NOT modify business logic, data fetching, or application state.


Phase 5: Report & Backlog

5.1 Read Stage 2 Files

Read deferred files:

  3. ../../shared/includes/run-logger.md      -- [READ | MISSING -> STOP]
  4. ../../shared/includes/retrospective.md      -- [READ | MISSING -> STOP]
  5. ../../shared/includes/backlog-protocol.md -- [READ | MISSING -> degraded]

5.2 Scoring

Per-dimension scoring: Each dimension has a max weight. Score = sum of check scores within dimension.

Overall score: (total earned / total possible) * 100 — A10 excluded from score (legal risk section only, max = 76 from A1-A9).

Critical gates (explicit pass thresholds):

  • A2 (Keyboard Navigation) < 6/12 --> automatic FAIL regardless of overall score
  • A4 (Color & Contrast) < 5/10 --> automatic FAIL regardless of overall score

Grade thresholds:

GradeScoreCondition
A>= 85%All critical gates pass
B>= 70% and < 85%All critical gates pass
FAIL< 70%OR any critical gate fails

VERDICT mapping for run log — A → PASS, B → WARN, FAIL → FAIL; a failing critical gate forces FAIL at any score.

Two things this table used to get wrong. The bands were written 70-84 / >= 85, so a real 84.4% matched neither. And the verdict line said "PASS (A or B), WARN (B with critical gate borderline)", which both contradicted the field-resolution section below (there, 70-84% maps to WARN, not PASS) and invented a state the table forbids — B already requires every critical gate to pass, so "B with a borderline gate" cannot occur, and "borderline" is defined nowhere. A critical gate is PASS or FAIL; there is no third position.

5.3 Report Output

REQUIRED: emit the Tool Availability Block (template in ../../shared/includes/codesift-setup.md) at the top of the report, after the title and before findings. Auditing degraded runs depends on this — do NOT skip it.

ACCESSIBILITY AUDIT REPORT
===============================================
Project: [name]
Date: [ISO-8601 date]
Framework: [detected]
Component Library: [detected or "custom"]
Standard: WCAG 2.2 [AA|AAA]
Legal: [ADA Title II | EAA | Section 508 | N/A]
A11y Tooling: [detected tools or "none"]

SCORE: [N]% -- Grade [A/B/C/FAIL]
===============================================

## Critical Gate Status
  A2 (Keyboard Navigation): [PASS/FAIL] ([N]/12)
  A4 (Color & Contrast):    [PASS/FAIL] ([N]/10)

## Dimension Scores
| # | Dimension | Score | Max | Key WCAG Criteria |
|---|-----------|-------|-----|-------------------|
| A1 | Semantic HTML | [N] | 10 | 1.3.1, 4.1.2 |
| A2 | Keyboard Navigation | [N] | 12 | 2.1.1, 2.1.2, 2.4.7 |
| A3 | ARIA Patterns | [N] | 10 | 4.1.2, 4.1.3 |
| A4 | Color & Contrast | [N] | 10 | 1.4.1, 1.4.3, 1.4.11 |
| A5 | Forms & Inputs | [N] | 10 | 1.3.1, 3.3.1, 3.3.2 |
| A6 | Images & Media | [N] | 8 | 1.1.1, 1.2.1, 1.2.2 |
| A7 | Responsive & Zoom | [N] | 6 | 1.4.4, 1.4.10 |
| A8 | Motion & Animation | [N] | 5 | 2.2.2, 2.3.1, 2.3.3 |
| A9 | Reading & Content | [N] | 5 | 2.4.2, 3.1.1, 3.2.3 |
| A10 | Legal Compliance | [N] | 4 | (aggregate) |
| | **Total** | **[N]** | **80** | |

## Findings (sorted by legal risk, then user impact)

### A11Y-001: [Title]
  Dimension: A[N]
  WCAG: [criterion number and name]
  Severity: CRITICAL | HIGH | MEDIUM
  File: [path:line]
  Impact: [who is affected and how]
  Fix: [specific code change or reference to Phase 4 fix]

### A11Y-002: [Title]
  ...

## Legal Compliance Summary
| Standard | Status | Key Gaps |
|----------|--------|----------|
| WCAG 2.2 AA | [PASS / PARTIAL / FAIL] | [summary] |
| ADA Title II | [COMPLIANT / AT RISK / NON-COMPLIANT / N/A] | [summary] |
| EAA | [COMPLIANT / AT RISK / NON-COMPLIANT / N/A] | [summary] |
| Section 508 | [COMPLIANT / AT RISK / NON-COMPLIANT / N/A] | [summary] |

## Automated vs Manual Coverage
  Automated checks (axe-core/pa11y): [N issues found | "not run"]
  Static code analysis: [N issues found]
  Manual verification needed: [N items flagged as CANNOT DETERMINE]

## Per-Component Breakdown
| File | A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | Total | Grade |
|------|----|----|----|----|----|----|----|----|----|----- -|-------|
| [path] | [N] | [N] | [N] | [N] | [N] | [N] | [N] | [N] | [N] | [N]% | [A-FAIL] |

5.4 Backlog Persistence

One rule: when --persist-backlog is set, or the run has at least one CRITICAL finding, every CRITICAL or HIGH finding of the run goes through backlog-add (the HIGH ones too, not only the CRITICAL that triggered it), one call per finding (../../shared/includes/backlog-protocol.md "Filing from a skill"; the bars and the dedupe are the protocol's, so compute no fingerprint and no seen count). With neither the flag nor a CRITICAL finding, nothing is recorded. <level> is critical or high.

A Generic write per finding. In the repository, an A2 keyboard trap or an A5 form finding that names the input and the wrong result is a BUG file record, and takes --anchor "$A", copied from the line that shows the defect or, for something absent (a control with no label, no key handler), from the line of the code that lacks it ("The location rule"): ~/.zuvo/backlog-add --repo "$R" --class BUG --conf <N> --source a11y-audit --file "$F" --line <n> --anchor "$A" --severity <level> --title "$T". Every other finding is a CQ, with no anchor: ~/.zuvo/backlog-add --repo "$R" --class CQ --conf <N> --source a11y-audit --file "$F" --line <n> --severity <level> --title "$T"; a finding that covers the whole component is a whole-file finding (--line 1, a "Whole file: ..." title).

A Phase 2 finding on the live page with no repository file causing it is a target record, which takes no anchor at all (--target "$U" --evidence "$E" in place of --file, --line and --anchor), with U the page URL and its own class by the same test: a BUG for an A2 or A5 finding that names the input and the wrong result, ~/.zuvo/backlog-add --repo "$R" --class BUG --conf <N> --source a11y-audit --target "$U" --evidence "$E" --severity <level> --title "$T"; otherwise a CQ, ~/.zuvo/backlog-add --repo "$R" --class CQ --conf <N> --source a11y-audit --target "$U" --evidence "$E" --severity <level> --title "$T". E holds the axe-core rule, the selector and the element's tag and attributes without any value= attribute or field content, and U has no query string; a secret or user data is never copied into a record (backlog-protocol.md "Filing from a skill", "The location rule", the secrets sentence).

Assign "$R" and "$T" before each call, "$F" and "$A" only for a file finding ("$A" only for a BUG), "$U" and "$E" only for a live-page finding, as "Free text goes through a variable" in that section says; an empty value you pass is a bug, and backlog-add refuses a missing required field (REFUSED missing-field:<f>). Report the B- or F-id each call prints and Recorded: N (backlog: a, ledger: b) ("The report line" in backlog-protocol.md), plus each NOT PERSISTED (<reason>) by name; on a non-zero exit act on the protocol's exit table, and never append by hand.

This audit does not commit: it stages nothing. It lists the wrote= paths backlog-add printed as Backlog writes: <path>, ... (Backlog writes: none when there are none), in its report for the user when it runs standalone, and in its report for the calling skill's closing commit to carry when another skill runs it (backlog-protocol.md "Filing from a skill", Committing what backlog-add wrote).

5.5 Save Report

Save to: zuvo/audits/a11y-audit-YYYY-MM-DD.md — at the project root (zuvo/ resolves via git rev-parse --show-toplevel; override $ZUVO_OUTPUT_DIR. See ../../shared/includes/report-output-location.md).

5.6 Propose Next Actions

FindingActionCommand
Critical gate A2 failureFix keyboard navigationzuvo:build fix keyboard traps in [component]
Critical gate A4 failureFix contrastzuvo:build update color tokens for WCAG contrast
Multiple A3 ARIA issuesFix ARIA patternszuvo:build add ARIA attributes to [component]
A5 form issuesFix form accessibilityzuvo:build add form labels and error association
No a11y toolingAdd eslint-plugin-jsx-a11yzuvo:build add eslint-plugin-jsx-a11y
Broad failures (Grade C/FAIL)Full multi-agent UI reviewzuvo:ui-design-team [path]
DX12-DX17 also failingRun design-reviewzuvo:design-review [path]

Completion Gate Check

Before printing the final output block, verify every item. Unfinished items = pipeline incomplete.

COMPLETION GATE CHECK
[ ] A11y tooling detection printed
[ ] Critical gates printed: A2 (Keyboard) and A4 (Contrast)
[ ] Per-component score table present with all A1-A9 dimensions
[ ] Findings sorted by legal risk first
[ ] Report saved to zuvo/audits/
[ ] Run: line printed and appended to log

Completion

After completing the audit, print:

A11Y-AUDIT COMPLETE
-----
Components audited: [N]
Standard: WCAG 2.2 [AA|AAA]
Score: [N]% -- Grade [A/B/C/FAIL]
Critical gates: A2=[PASS/FAIL] A4=[PASS/FAIL]
Findings: [N] CRITICAL, [N] HIGH, [N] MEDIUM
Fixes generated: [N] (if --fix)
Legal: [status summary]
Run: <ISO-8601-Z>	a11y-audit	<project>	<score>%	-	<VERDICT>	-	<N>-dimensions	<NOTES>	<BRANCH>	<SHA7>	<INCLUDES>	<TIER>
-----

Validity Gate (REQUIRED — print BEFORE Run line, AFTER retro append + append-runlog)

VALIDITY GATE
  required_tool_calls:
    get_file_tree: [<N> | NOT_CALLED]
    search_text: [<N> | NOT_CALLED]
    search_symbols: [<N> | NOT_CALLED]
    search_patterns: [<N> | NOT_CALLED]
    audit_scan: [<N> | NOT_CALLED]
    react_tools: [<result> | not_required | NOT_CALLED]
  postamble:
    retros_log_appended: [yes(bytes_added=N) | NOT_APPENDED]
    retros_md_appended: [yes(entry_count=N) | NOT_APPENDED]
    verify_audit_pass: [yes(<verified>/<total>) | NOT_RUN | REJECTED]
  gate_status: [PASS | FAIL]

If gate_status = FAIL → VERDICT = INCOMPLETE. Append the Run line via the retro-gated wrapper (NOT direct >> runs.log):

printf '%b\n' "$RUN_LINE" | ~/.zuvo/append-runlog

Retrospective (REQUIRED)

Follow the retrospective protocol from retrospective.md. Gate check → structured questions → TSV emit → markdown append. If gate check skips: print "RETRO: skipped (trivial session)" and proceed.

After printing this block, append the Run: line value (without the Run: prefix) to the log file path resolved per run-logger.md.

Field resolution:

  • CQ_SCORE: <score>% (overall percentage)
  • Q_SCORE: - (not applicable)
  • VERDICT: PASS (>= 85%), WARN (>= 70% and < 85%), FAIL (< 70%, or any critical gate fails)
  • TASKS: -
  • DURATION: <N>-dimensions (number of dimensions scored, typically 10)
  • NOTES: WCAG2.2-[AA|AAA] [N]-findings [legal-status] (max 80 chars)

Next-Action Routing

FindingActionCommand
Keyboard traps, missing focusFix keyboard navigationzuvo:build [description]
Contrast failuresFix color tokenszuvo:build [description]
Missing ARIA on componentsFix ARIA patternszuvo:build [description]
Form a11y gapsFix form accessibilityzuvo:build [description]
Broad design issuesMulti-agent UI reviewzuvo:ui-design-team [path]
Surface-level DX checksDesign consistency auditzuvo:design-review [path]
Security concerns surfacedSecurity auditzuvo:security-audit [path]

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.