- name
- accessibility
- description
- Consolidated accessibility skill entrypoint for WCAG 2.2, ARIA Authoring Practices, cognitive accessibility, Section 508, EN 301 549, design intent verification, and the Accessibility Planner workflow.
- license
- MIT
- compatibility
- Requires Python 3.11+ and uv; the scanner additionally needs Node.js and network access to fetch the pinned axe-core CLI from the public npm registry.
- user-invocable
- false
- metadata
- {"authors":"microsoft/hve-core","spec_version":"1.0","last_updated":"2026-10-02"}
# Accessibility — Skill Entry
This skill is the canonical accessibility reference contract for HVE Core. Agents and instructions invoke this skill by name and rely on it to own framework reference resolution, phase guidance resolution, and the scanner CLI entrypoint.
## Framework references
* [WCAG 2.2](references/frameworks/wcag-22.md)
* [ARIA Authoring Practices Guide](references/frameworks/aria-apg.md)
* [Cognitive Accessibility Guidance](references/frameworks/coga.md)
* [Section 508](references/frameworks/section-508.md)
* [EN 301 549](references/frameworks/en-301-549.md)
* [Graphics ARIA and SVG-AAM](references/frameworks/graphics-aria-svg-aam.md)
Assessment reference (cross-cutting, not a conformance framework):
* [Assistive-technology announcement model](references/frameworks/at-announcement-model.md) — read this when deciding the announcement-class criteria (WCAG 1.3.1, 4.1.2, 4.1.3): what a screen-reader user should hear, and how to decide it with an accessibility-tree assertion or a manual AT pass.
## Accessibility Planner workflow
The Accessibility Planner runs six phases, each keyed to a state id:
1. Phase 1 — Discovery (`discovery`)
2. Phase 2 — Framework Selection (`framework-selection`)
3. Phase 3 — Standards Mapping (`standards-mapping`)
4. Phase 4 — Plan Risk Assessment (`plan-risk-assessment`)
5. Phase 5 — Impact and Evidence (`impact-evidence`)
6. Phase 6 — Backlog Handoff (`backlog-handoff`)
## Phase reference index
* Phase 1 — Discovery: [capture-coaching.md](references/phases/capture-coaching.md) — read this when running exploration-first capture questioning.
* Phase 2 — Framework Selection: [framework-selection.md](references/phases/framework-selection.md) — read this when choosing which frameworks and conformance level apply.
* Phase 3 — Standards Mapping: walk the [framework references](#framework-references) roll-up tables to emit `controlMappings`; consumed by Phase 5. No dedicated file — mapping is driven by the framework roll-ups.
* Phase 4 — Plan Risk Assessment: [capture-coaching.md](references/phases/capture-coaching.md) governs the questioning posture when escalation triggers reopen scoping; tier criteria are applied per the Accessibility Planner identity instructions and recorded as `riskClassification.tier`. No dedicated file — the accessibility risk surface is narrow enough to stay inline.
* Phase 5 — Impact and Evidence: [impact-assessment.md](references/phases/impact-assessment.md) — read this when building the evidence register, tradeoff log, and seed work-items.
* Phase 6 — Backlog Handoff: [backlog-handoff.md](references/phases/backlog-handoff.md) — read this when rendering work items and validating handoff gates.
## Method adequacy (decide vs inform)
Method adequacy is the doctrine that a verification method may only be recorded as satisfying a success criterion when that method can actually *decide* the criterion. A method that can observe a related signal but cannot confirm the user-facing outcome only *informs* the criterion; it raises or lowers suspicion but never closes it. This section is the canonical definition; the planner evidence register, the reviewer verdict logic, and the runtime probe harness all resolve adequacy through it.
The machine-readable adequacy source is [scripts/runtime_a11y/probe-criteria-map.json](scripts/runtime_a11y/probe-criteria-map.json). Each probe entry lists the criteria it `decides` and the criteria it only `informs`. A result counts as adequate only when the winning method appears in the `decides` list for that criterion and state.
### Failure classes and adequate methods
Accessibility defects generalize into five classes. Static analysis (axe, `eslint-plugin-jsx-a11y`, snapshot structure counts) can decide only the first class; the remaining four require an interaction-state probe or an assistive-technology (AT) pass to be decided rather than merely informed.
| Class | Representative WCAG SC | What static analysis can do | Adequate method to decide |
|--------------------------------|--------------------------------------------------|-----------------------------|-------------------------------------------------------------------------------------------------------------|
| **Static-decidable structure** | 1.1.1, 1.4.3, 4.1.2 (name present), 2.4.2, 3.1.1 | Decide | axe / static scan |
| **Interaction behavior** | 2.1.1, 2.1.2, 2.4.3, 2.4.7, 2.4.11 | Inform only | Keyboard/interaction probe driving keys across `focus`/`open` states, or manual keyboard pass |
| **Announcement correctness** | 1.3.1, 4.1.2 (computed name/role), 4.1.3 | Inform only | Accessibility-tree assertion of computed name/role/live, or manual AT pass (Windows NVDA or human-led JAWS) |
| **Adaptive rendering** | 1.4.4, 1.4.10, 1.4.12, 2.4.11 | Inform only | Rendered probe at 200% zoom, 320px reflow, and text-spacing states |
| **Faux semantics** | 1.3.1 (faux headings), 2.4.3 (faux controls) | Cannot see | Heuristic source pass plus accessibility-tree assertion; no element exists for a rule engine to flag |
For the announcement class, the [assistive-technology announcement model](references/frameworks/at-announcement-model.md) specifies what the user should hear per criterion and how to decide it. For the interaction and faux-semantics classes, the [focus-management anti-pattern catalog](references/frameworks/aria-apg.md#focus-management-anti-patterns) enumerates the defects that pass a static scan yet break keyboard and screen-reader users.
### Adequacy rule
* A control in the interaction, announcement, adaptive-rendering, or faux-semantics classes cannot be recorded as fully satisfied on static evidence alone. Static evidence caps such a control at a partial state until an adequate method is attached.
* A criterion whose winning method only `informs` it is never a conformance verdict; it is a lead that routes to an adequate method or a manual pass.
* Preserve the adequacy determination alongside the status so downstream planners and reviewers do not re-promote an inadequately verified control.
This doctrine and its class taxonomy are repository-original content licensed under CC BY 4.0; the underlying success-criterion definitions remain with WCAG 2.2 as cited in [wcag-22.md](references/frameworks/wcag-22.md).
### Calibration is evidence quality, not a conformance verdict
Calibration establishes that the assistive-technology stack behaves as expected before its output is trusted. Its checkpoints record driver identity, profile fingerprint, and artifact hashes for a journey that passed.
A checkpoint is deliberately not a matrix input. Nothing in the coverage or outcome pipeline reads one, and that separation is intended rather than unfinished. A passing calibration says the harness was working; it does not say the surface satisfies a success criterion. Wiring checkpoints into coverage would turn a statement about the tool into a statement about the product.
If calibration evidence should ever influence coverage, that is new design work requiring its own review: it needs an explicit mapping from a journey to a criterion, surface, and state, and it must respect the same method-adequacy rules as any other evidence.
### Gate strictness by assessment tier
The enforcement posture for the interaction, announcement, adaptive-rendering, and faux-semantics classes graduates with the assessment depth tier recorded in `riskClassification.tier`, so the gate inherits the rigor a project opted into rather than applying one global switch:
* `basic` — the adequate-method probes (keyboard, widget-keyboard, live-region, aria-tree, virtual-sr) report **advisory** (warn-only); the always-decidable core probes still block.
* `standard` (default) — **ratchet**: the adequate-method probes block on new or changed surfaces and stay advisory over the existing backlog, so no new defect in these classes ships while legacy content is surfaced without freezing the project.
* `comprehensive` — the adequate-method probes **block** on every in-scope surface.
The always-decidable core probes (axe, DOM hygiene, broken links, console errors, target size, contrast, reflow/resize) block at every tier. The CI workflow template implements this dial through the `A11Y_TIER` and `A11Y_RATCHET_SURFACES` inputs; the Accessibility Reviewer applies the same graduation to its FAIL and PARTIAL verdicts.
## Tooling
The scanner CLI ([scripts/scan.py](scripts/scan.py)) wraps the Node-based axe-core scanner and normalizes its findings into a stable JSON shape.
### Prerequisites
* Python 3.11+ with [uv](https://docs.astral.sh/uv/) available on PATH.
* Node.js with `npx` available on PATH.
* Network access on first run so `npx` can fetch `@axe-core/cli`.
### Quick Start
```bash
uv run scripts/scan.py https://example.com --allow-host example.com
uv run scripts/scan.py ./page.html --output results.json
uv run scripts/scan.py file:///path/to/page.html
```
Loopback HTTP(S) targets need no additional option. Every other remote host
requires either a matching, repeatable `--allow-host HOST` value or the broader
`--allow-external` confirmation. Local paths and local `file:` URIs must resolve
to existing regular files. Network shares, remote file authorities, directories,
missing files, credentials, leading-dash targets, and non-HTTP(S) remote schemes
are rejected before the axe CLI starts.
### Parameters Reference
| Parameter | Required | Default | Description |
|--------------------|----------|---------|----------------------------------------------------------------|
| `target` | Yes | — | Authorized HTTP(S) URL or existing regular local file to scan. |
| `--output` | No | stdout | Path to write the normalized JSON results. |
| `--allow-host` | No | none | Authorize one non-loopback HTTP(S) host; repeat as needed. |
| `--allow-external` | No | false | Confirm access to any non-loopback HTTP(S) host. |
Remote authorization applies to the initial scanner target only. It does not
constrain browser redirects, DNS address changes, subresources, WebSockets,
Service Workers, downloads, or other browser-derived requests. Run the scanner
only from a workstation whose network reach matches the target's trust level.
### Script Reference
* Entrypoint: [scripts/scan.py](scripts/scan.py)
* Output shape:
```json
{
"target": "<scanned target>",
"summary": {
"violations": 0,
"passes": 0,
"incomplete": 0,
"inapplicable": 0
},
"violations": [
{ "id": "", "impact": "", "description": "", "nodes": 0 }
]
}
```
* Exit codes:
* `0` — scan completed successfully.
* `1` — scan failed or returned invalid output.
* `2` — scanner unavailable (Node.js or `@axe-core/cli` missing).
### Troubleshooting
| Symptom | Likely cause | Action | Exit code |
|------------------------------------------|--------------------------------------------|------------------------------------------------------------------|-----------|
| `scanner unavailable` error | Node.js or `npx` not on PATH | Install Node.js so `npx` resolves, then re-run. | `2` |
| Long pause or download on first run | `npx` is fetching `@axe-core/cli` | Allow network access on the first run; later runs use the cache. | — |
| `Refusing to probe non-loopback host` | Remote host was not explicitly authorized | Add `--allow-host HOST` or confirm with `--allow-external`. | `2` |
| `Local scan target does not exist` | Local path or file URI cannot be resolved | Supply an existing regular local file, not a directory or share. | `2` |
| `scan failed or returned invalid output` | axe-core CLI errored or emitted non-JSON | Confirm the target URL or file is reachable and well-formed. | `1` |
| Empty `violations` but issues expected | Page rendered after the scan, or rules N/A | Confirm the target fully loads; check `summary.inapplicable`. | `0` |
### Mapping findings to frameworks
Each violation's `impact` is one of `minor`, `moderate`, `serious`, or `critical`. axe rule tags decode to WCAG success criteria by stripping the `wcag` prefix and inserting decimals:
| axe tag | WCAG success criterion |
|-----------|--------------------------|
| `wcag111` | 1.1.1 Non-text Content |
| `wcag143` | 1.4.3 Contrast (Minimum) |
WCAG success criteria are normative; the axe techniques that surface them are informative. Treat scanner output as evidence pointing at a criterion, not a conformance verdict.
### Runtime probe harness
The runtime probe harness ([scripts/runtime_a11y](scripts/runtime_a11y)) runs Playwright-based accessibility probes against a project-specific surface inventory and aggregates the results into a coverage matrix. For workflow orchestration, ask the user to run the manual-only `accessibility-coverage-matrix` skill (`/accessibility-coverage-matrix`); it is not model-invocable. Use the `Accessibility Surface Inventory` subagent as the canonical producer of the runtime config. Activate it by name; when it does not resolve, warn the user that the capability is unavailable and stop the dependent step.
#### Harness prerequisites
Complete these once before any runtime-harness command. They are separate from the `scan.py` prerequisites above.
* Python 3.11+ with [uv](https://docs.astral.sh/uv/) available on PATH.
* Node.js available on PATH, plus system Google Chrome, because the probes target `channel: 'chrome'`.
* Skill-local Node dependencies installed under [scripts/runtime_a11y](scripts/runtime_a11y). The CLI fails fast with an install hint when they are missing.
* Automated Windows NVDA runs additionally require the manifest-selected Guidepup NVDA asset. Machine setup and asset installation are separate actions from `npm ci`.
Install the harness dependencies from the `scripts/runtime_a11y` directory:
```bash
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm ci
```
```powershell
$env:PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = '1'; npm ci
```
`PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1` avoids downloading bundled browsers that the harness never uses.
For automated NVDA runs, prepare the Windows machine once, then install the asset selected by the skill-local Guidepup package. Run the asset command again after updating Guidepup:
```powershell
Set-Location <skill-root>/scripts/runtime_a11y
npx --yes --registry=https://registry.npmjs.org/ @guidepup/setup@0.25.3 setup
npx --yes --registry=https://registry.npmjs.org/ @guidepup/setup@0.25.3 install nvda
```
The commands configure the machine and write versioned assets to the Guidepup user cache. They are not part of ordinary dependency installation. Run the prerequisite-only probe before a calibration session:
```bash
uv run scripts/runtime_a11y/__main__.py run-calibration --config <path-to>/a11y-runtime.config.json --prerequisite-only
```
The preflight reports the skill-local library, manifest-selected NVDA asset, and any conflicting NVDA process independently. Do not start a personal NVDA instance before an automated run; the harness starts an isolated session and rejects an existing process.
Ver en GitHub